首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在获得证书的api请求中对IPFS节点使用带CORS的fetch

如何在获得证书的api请求中对IPFS节点使用带CORS的fetch
EN

Stack Overflow用户
提问于 2021-03-27 10:28:29
回答 1查看 823关注 0票数 0

我想将经过身份验证的请求发送到IPFS端点(在nginx后面),但是我很难同时拥有CORS请求头和授权令牌权限。

以下是我如何尝试这样做的:

代码语言:javascript
运行
复制
let auth='dXNlcjpwYXNzd29yZA=='
let url = 'https://url.of.api.endpoint.test'
let headers = new Headers();
// headers.set('Authorization', `Basic ${auth}`);
fetch(url,{ method:'POST', credentials: 'include', headers: headers })
.catch(console.error)

如果我添加了一个凭据:'include',那么我得到了403个响应,因为浏览器没有发送授权头,如果我有一个“授权:基本xxx”的标题,那么飞行前就停止向我发送正确的允许源。

同一原点上的页面运行正常:https://ipfs.blockringtm.ml/ipfs/QmZ3wTVb7WeZZAk8g7pczprZcjqswBxhr7GrCNdPna8jac/posting.html

而下面这一页没有:

http://127.0.0.1:8080/ipfs/QmZ3wTVb7WeZZAk8g7pczprZcjqswBxhr7GrCNdPna8jac/posting.html

它在飞行前的选项失败了!

代码语言:javascript
运行
复制
XHR: OPTIONS https://ipfs.blockringtm.ml/api/v0/add?file=foobar.dat&cid-version=0
CORS Missing Allow Origin

OPTIONS https://ipfs.blockringtm.ml/api/v0/add?file=foobar.dat&cid-version=0
Status: 200 OK
Version: HTTP/2
Transferred: 324 B (0 B size)
Referrer Policy: no-referrer-when-downgrade

    HTTP/2 200 OK
    server: nginx
    date: Sat, 27 Mar 2021 10:13:09 GMT
    content-length: 0
    vary: Origin
    vary: Access-Control-Request-Method
    vary: Access-Control-Request-Headers
    strict-transport-security: max-age=15768000; includeSubDomains; preload
    x-content-type-options: nosniff
    x-xss-protection: 1; mode=block
    X-Firefox-Spdy: h2

XHRequest: 
    Accept:     */*
    Accept-Encoding:    gzip, deflate, br
    Accept-Language:    en-US,en;q=0.5
    Access-Control-Request-Headers:     authorization
    Access-Control-Request-Method:      POST
    Connection:     keep-alive
    Host:       ipfs.blockringtm.ml
    Origin:     http://127.0.0.1:8080
    Referer:    http://127.0.0.1/
    Sec-GPC:        1
    User-Agent:     Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0

问题how to do a proper credentialed CORS request with fetch ?

下面是更多细节..。

我的IPFS节点配置如下:

代码语言:javascript
运行
复制
{ "API": {
   "HTTPHeaders": {
      "Access-Control-Allow-Credentials": [
         "true"
      ],
      "Access-Control-Allow-Headers": [
         "Authorization, Content-Type"
      ],
      "Access-Control-Allow-Methods": [
         "GET",
         "POST"
      ],
      "Access-Control-Allow-Origin": [
         "http://127.0.0.1:8080",
         "http://localhost:8088",
         "https://webui.ipfs.io"
      ],
      "Access-Control-Expose-Headers": [
         "Location"
      ]
   }
}
}

Nginx反向代理配置如下:

代码语言:javascript
运行
复制
  location /api/ {
    proxy_pass  http://michelc_ipfs_api;

    proxy_read_timeout 600;
    proxy_send_timeout 600;

    #max upload size 2G
    client_max_body_size  2048m;

    # Adding missing CORS header from IPFS API response
    if ($remote_method = 'OPTIONS') {
      add_header Access-Control-Allow-Headers "Authorization";
    }

    limit_except OPTIONS {
      auth_basic "Restricted Content";
      auth_basic_user_file /home/michelc/htpasswd;
    } 
  }   

当我不使用凭据并将模式设置为“cors”时,它可以工作(需要在127.0.0.1:5001上运行api的本地ipfs守护进程):http://127.0.0.1:8080/ipfs/QmT3f4LdMsTv47swcA298sBTPF95Bz8M5sFfBAuHKKiyWo/posting-nocreds.html

  1. 验证飞行前工作:

代码语言:javascript
运行
复制
curl -i -X 'OPTIONS' 'http://127.0.0.1:5001/api/v0/add?file=foobar.dat&cid-version=0' \
 -H 'Origin: http://127.0.0.1:8080' -H "Access-Control-Request-Headers: authorization"

答案看起来是正确的:它有适当的允许-起源!:

代码语言:javascript
运行
复制
HTTP/1.1 204 No Content
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:8080
Allow: OPTIONS, POST
Vary: Origin
Date: Sat, 27 Mar 2021 07:58:56 GMT

authentication:

  1. 测试

代码语言:javascript
运行
复制
auth='c286YW5vbnltb3Vz'
curl -i -X POST "https://ipfs.blockringtm.ml/api/v0/add?file=key.json&wrap-with-directory=true&quiet=true&quieter=true&cid-version=0"   -H "Origin: http://127.0.0.1:8080" -H "Authorization: Basic ${auth}" -F "file=why, hello!"

反应看起来也不错:

代码语言:javascript
运行
复制
server: nginx
date: Sat, 27 Mar 2021 09:25:37 GMT
content-type: application/json
vary: Accept-Encoding
access-control-allow-credentials: true
access-control-allow-headers: X-Stream-Output, X-Chunked-Output, X-Content-Length
access-control-allow-origin: http://127.0.0.1:8080
access-control-expose-headers: X-Stream-Output, X-Chunked-Output, X-Content-Length
trailer: X-Stream-Error
vary: Origin
x-chunked-output: 1
strict-transport-security: max-age=15768000; includeSubDomains; preload
x-content-type-options: nosniff
x-xss-protection: 1; mode=block

{"Name":"QmWiziLpQ37PhV671gj6zPnWMGxdCKpBwdQVGbmWJmqFvE","Hash":"QmWiziLpQ37PhV671gj6zPnWMGxdCKpBwdQVGbmWJmqFvE","Size":"19"}
{"Name":"","Hash":"QmWZU5LLRcPmgZrvTkJuhRYmujEYCpvP8Efz1BqKM5AkRx","Size":"111"}

为了进一步调试,我安装了一个本地证书,以便让本地主机使用SSL为我提供文件服务,并使用映射设置nginx,问题是我无法杀死来自IPFS守护进程的坏头。

因此,我尝试将最小值传递给IPFS并处理ngynx中的CORS:

代码语言:javascript
运行
复制
# api keys :
map $http_x_apikey $api_realm {
    default "";
    "**secret1**" "IRQ";
    "**secret2**" "key_id";
    "**secret3" "ipns_key";
    "**secret4**" "api_key";
    "**secret5**" "key_add";
    "**secret6**" "key_name";
    "**secret7**" "key_provs";
    "**secret8**" "key_config";
}
# $request_uri has the query part, $uri doesn't 
map $request_uri $req_api {
 default "not-an-api-req";
 ~^/api/v0/[^?]+?key=IRQ "${api_realm}line";
 ~^/api/v0/([^?]*) "${api_realm}_req_$1";
}

map $req_api $match_realm {
  default no;
  "IRQline" yes;
  "key_id_req_id" yes;
  "key_add_req_add" yes;
  "key_provs_req_dht/findprovs" yes;
  "key_name_req_name" yes;
  "key_name_req_resolve" yes;
  "key_config_req_config" yes;
  "ipns_key_req_name/publish" yes;
  "api_key_dht/findprovs" yes;
}

map $http_origin $allow_origin {
  default no;
  ~http://127.0.0.1(?::[0-9]+)? yes;
  ~http://172.17.0.[0-9]+(?::[0-9]+)? yes;
  ~http://.*localhost: yes;
  ~https://gateway\..* yes;
  ~https://ipfs\..* yes;
  "https://bl.ocks\.org" yes;
}

# pass origin if $allow_oring = no
map $allow_origin $proxy_pass_origin {
  yes "";
  no $http_origin;
  default $http_origin;
}

# add_header Access-Control-Allow-Origin $http_origin
map $allow_origin $header_allow_origin {
  default "";
  yes $http_origin;
  no "http://blockringtm.ml";
  all "*";
}
map $allow_origin $header_allow_credential {
  default "";
  yes true;
}
# add_header Access-Control-Allow-Credentials true;
map $allow_origin $header_allow_credentials {
  default "";
  yes true;
}
# add_header Access-Control-Allow-Methods '$request_method';
map $allow_origin $header_request_method {
  default "";
  yes $request_method;
}
map $allow_origin $post_only {
  default "OPTIONS";
  yes "POST";
}
# add_header Access-Control-Allow-Headers "$http_access_control_request_headers";
map $allow_origin $header_request_headers {
  default "";
  yes $http_access_control_request_headers;
}
# authorization header
map $http_authorization $request_auth_header {
  default "";
  ~Basic "authorization";
}
map $allow_origin $header_authorization {
 default "";
 yes $request_auth_header;
}



# global variables & maps
map $host $dbug { default 1; } # to allow more visibility !

map $dbug $x_name { default ""; 1 "Vern J. Guerrini"; }

map $dbug $x_loc_api { 1 "location $1"; default ""; }
map $dbug $x_req_api { 1 "$req_api"; default ""; }
map $dbug $x_api_realm { 1 "$api_realm"; default ""; }
map $dbug $x_match_realm { 1 "$match_realm"; default ""; }
map $dbug $x_allow_origin { 1 "$allow_origin"; default ""; }
map $dbug $x_uri { 1 "$uri"; default ""; }
map $dbug $x_request_uri { 1 "$request_uri"; default ""; }


map $request_uri $readonly {
    default yes;
    ~^/api/v0/add no;

server {
  ...
  proxy_set_header Authorization '';
  proxy_set_header X-APIKey '';
  # API key validation
  location = /authorize_apikey {
     internal;
     if ($request_method = 'OPTIONS') {
        return 204;
     }
     if ($api_realm = "") {
        return 403; # Forbidden
     }
     if ($http_x_apikey = "") {
        return 401; # Unauthorized
     }
     if ($match_realm = 'no') { return 200 "req_api and key_realm don't match"; }
     
     return 204; # OK (no content)
  }
  ...
  # allow /api/v0/... with api-key or password
  location ~* ^/api/v0/(add|resolve|object|name|dht|key/list|id) {
     proxy_read_timeout 600;
     proxy_send_timeout 600;
     proxy_pass  http://ipfs-api;
     client_max_body_size 4m;

     # debug headers 
     add_header x-dbug "$dbug";
     #set $x_dbug "";
     #if ($dbug = 1) { set $x_dbug "debug !"; }
     add_header x-name "$x_name";
     add_header x-loc_api "location matches $1";
     add_header x-allow-origin "$allow_origin";
     add_header x-api-realm "$api_realm";
     add_header x-req-api "$x_req_api";
     add_header x-header-requested "$header_request_headers";

     # pass origin if not allowed here!
     add_header x-proxy-pass-origin "$proxy_pass_origin";
     proxy_set_header Origin "$proxy_pass_origin";

     add_header Access-Control-Allow-Headers "x-apikey";
     proxy_set_header Access-Control-Request-Headers "x-apikey"; # "$http_access_control_request_headers";
     #proxy_set_header Access-Control-Request-Headers "$proxy_pass_request_headers";
     # conditional headers (if $allow_origin = yes)
     add_header Access-Control-Allow-Origin "$header_allow_origin";
     add_header Access-Control-Allow-Credentials "$header_allow_credentials";
     add_header Access-Control-Allow-Methods '$header_request_method';
     add_header Access-Control-Allow-Headers "$header_request_headers";

     #if ($request_method = 'OPTIONS') {
     #  add_header x-request-method "$request_method";
     #  add_header Access-Control-Allow-Credentials true;
     #  add_header Access-Control-Allow-Origin "$http_origin";
     #  add_header Access-Control-Allow-Methods 'POST';
     #  add_header Access-Control-Allow-Headers "$http_access_control_request_headers";
     #  return 200 'API $request_method call "$1" accepted from $http_origin';
     #}
     satisfy any;
     auth_request /authorize_apikey;
     limit_except OPTIONS {
        auth_basic "Restricted API ($req_api)";
        auth_basic_user_file /etc/nginx/htpasswd-api-add;
     }
  }
}

它仍然不起作用,IPFS的响应干扰了nginx CORS!

如何进行经过身份验证的ajax调用?使用Basic以外的其他身份验证: JWT,cookie?我想要更多的学习正确的方法,而不是一个快速的黑客,我们绕过CORS。

EN

回答 1

Stack Overflow用户

发布于 2021-03-29 17:02:59

考虑到您已经在Nginx级别为/api/v0添加了自定义路由和基本auth,我认为您将有更好的时间在Nginx上设置所有CORS头。

这样,您就可以在一个地方拥有所有的逻辑,而不必在nginx和go配置之间进行权衡。

ps。如果没有Nginx配置,就不可能给出有意义的答案。下次填写这样的问题时,请把它包括在内。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66830278

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档