Nginx 如何在IPFS节点的认证api请求中使用带CORS的fetch

Nginx 如何在IPFS节点的认证api请求中使用带CORS的fetch,nginx,cors,fetch,ipfs,Nginx,Cors,Fetch,Ipfs,我想将经过身份验证的请求发送到IPFS api端点(在nginx后面),但是我很难同时获得CORS请求头和授权令牌 下面是我如何尝试的: 让auth='dXNlcjpwYXNzd29yZA==' 让url为空https://url.of.api.endpoint.test' let headers=新的headers(); //set('Authorization','Basic${auth}`); 获取(url,{method:'POST',凭据:'include',headers:heade

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

下面是我如何尝试的:

让auth='dXNlcjpwYXNzd29yZA=='
让url为空https://url.of.api.endpoint.test'
let headers=新的headers();
//set('Authorization','Basic${auth}`);
获取(url,{method:'POST',凭据:'include',headers:headers})
.catch(console.error)
如果我添加一个凭据:“include”,那么我会得到403响应,因为浏览器没有发送授权头 如果我有一个“Authorization:basic xxx”标题,那么飞行前会停止向我发送正确的allow origin

同一原点上的页面不起作用:
而下面的页面没有:

在选项飞行前失败

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

问题
如何使用fetch执行正确的认证CORS请求?

下面是更多的细节

我的IPFS节点配置了以下各项:

{“API”:{
“HTTPHeaders”:{
“访问控制允许凭据”:[
“对”
],
“访问控制允许标头”:[
授权,内容类型
],
“访问控制允许方法”:[
“得到”,
“职位”
],
“访问控制允许来源”:[
"http://127.0.0.1:8080",
"http://localhost:8088",
"https://webui.ipfs.io"
],
“访问控制公开标头”:[
“地点”
]
}
}
}
Nginx反向代理配置如下:

  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;
    } 
  }   

当我不使用凭据并将mode设置为“cors”时,它可以工作(需要一个本地ipfs守护程序在127.0.0.1:5001上运行api):

  • 验证飞行前工作:
  • curl-i-X'选项“”http://127.0.0.1:5001/api/v0/add?file=foobar.dat&cid-版本=0'\
    -H'来源:http://127.0.0.1:8080'-H“访问控制请求头:授权”
    
    答案看起来是正确的:它具有正确的允许原点!:

    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
    
  • 测试验证:
  • auth='c286YW5vbnltb3Vz'
    curl-i-X POST“https://ipfs.blockringtm.ml/api/v0/add?file=key.json&wrap-当directory=true&quiet=true&quieter=true&cid version=0“-H”原点时:http://127.0.0.1:8080“-H”授权:基本${auth}“-F”文件=为什么,您好
    
    回答看起来也不错:

    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"}
    
    
    
    为了进一步调试,我安装了一个本地证书,让localhost使用SSL为我提供文件,并使用映射设置nginx,问题是我无法消除来自IPFS守护进程的坏头

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

    # 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调用? 使用基本身份验证以外的其他身份验证:JWT、cookies?
    我想更多地了解正确的方法,而不是快速破解,我们绕过CORS。

    鉴于您已经在Nginx级别为
    /api/v0
    添加了自定义路由和基本身份验证,我觉得您在Nginx上设置所有CORS头也会有更好的时间

    这样,您就可以将所有逻辑放在一个地方,而不必在nginx和go-ipfs-config之间进行切换


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

    鉴于您已经在Nginx级别为
    /api/v0
    添加了自定义路由和基本身份验证,我觉得您在Nginx上设置所有CORS头的时间也会更好

    这样,您就可以将所有逻辑放在一个地方,而不必在nginx和go-ipfs-config之间进行切换


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

    似乎IPFS守护进程忽略了
    访问控制请求头,正如运行:`curl-i-X OPTIONS”“-H”Origin:“-H”访问控制请求头:authorization“``不返回任何关于允许头的信息!经过进一步调查,chromium上的脚本页面,而不是brave或firefox上的脚本页面。。。IPFS守护进程似乎忽略了
    访问控制请求头
    ,如下所示:`curl-i-X OPTIONS”“-H”Origin:“-H”访问控制请求头:authorization“``不返回任何关于允许头的信息!经过进一步调查,chromium上的脚本页面,而不是brave或firefox上的脚本页面。。。谢谢事实上,我希望cors只在一个地方,在我看来,让最终应用程序处理cors是合乎逻辑的(特别是我控制应用程序,而我不太容易控制nginx,因为它与一系列其他服务共享。让我编辑我的帖子来添加ningx config。谢谢……事实上,我只想将cors放在一个地方,在我看来,让最终应用程序处理它是合乎逻辑的(特别是我控制应用程序,而我控制nginx并不是那么容易,因为它与许多其他服务共享。让我编辑我的帖子,添加ningx配置。