如何在预检请求中强制进行身份验证?

时间:2021-06-26 15:02:44

标签: javascript cors github-api client-side preflight

我正在尝试从客户端 javascript(在浏览器中)调用 Github REST API。

我的代码执行以下操作(我正在尝试获取包含私有存储库分支 mkdocs_page 的 zip):

    const endpoint = 'https://api.github.com';
    const resource = '/repos/astariul/private-gh-pages/zipball/mkdocs_page';
    const options = {
      mode: 'cors',
      headers: {
        'Authorization': 'Basic ' + btoa(`${pat}`),  // pat contains my Personal Access Token
      }
    }

    return fetch(`${endpoint}${resource}`, options);

但它不起作用: enter image description here 预检请求因 404 失败。

控制台错误信息:

<块引用>

从源 'null' 访问 'https://api.github.com/repos/astariul/private-gh-pages/zipball/mkdocs_page' 已被 CORS 政策阻止:对预检请求的响应没有' t 通过访问控制检查:它没有 HTTP ok 状态。


在调试这个过程中,我尝试用curl重现问题。当我指定一个经过身份验证的请求时,它会起作用:

curl --user "<my_PAT_token>" -i https://api.github.com/repos/astariul/private-gh-pages/zipball/mkdocs_page -X OPTIONS
<块引用>

HTTP/1.1 204 无内容

但是如果请求没有经过身份验证,它就不起作用:

curl -i https://api.github.com/repos/astariul/private-gh-pages/zipball/mkdocs_page -X OPTIONS
<块引用>

HTTP/1.1 404 未找到


注意:当我尝试获取 master 分支(是否经过身份验证)时,它工作正常。但是,在重定向后失败:

<块引用>

访问“https://codeload.github.com/astariul/private-gh-pages/legacy.zip/refs/heads/main?token=XXX”(重定向自“https://api. github.com/repos/astariul/private-gh-pages/zipball') 来自 origin 'null' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:无 'Access-Control-Allow-Origin ' 请求的资源上存在标头。如果不透明响应满足您的需求,请将请求的模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。


这是 Github API 中的错误吗?还是我做错了什么?

1 个答案:

答案 0 :(得分:2)

无法在预检请求中强制进行身份验证。预检完全由浏览器控制,并且没有任何可以通过前端 JavaScript 代码操作的方式公开。并且 CORS 协议的要求明确禁止浏览器在预检请求中包含任何凭据。有关详细说明,请参阅 https://stackoverflow.com/a/45406085/ 处的答案。

由于预检涉及浏览器发出 OPTIONS 请求,因此一般而言,如果服务器需要对特定端点或资源的 OPTIONS 请求进行身份验证(GitHub 似乎就是这种情况)问题中引用的网址)这根本不一定是意外错误。

这是因为执行预检并发送 OPTIONS 请求的唯一正常情况是前端 JavaScript 代码在浏览器中运行的情况。从服务器端代码或在 shell/命令行环境中运行的代码或从桌面应用程序或本机移动应用程序发出的请求不涉及发送 OPTIONS 请求。

因此,如果提供者实际上打算从浏览器中运行的前端 JavaScript 代码中使用它,则缺乏对未经身份验证的 OPTIONS 对特定端点/资源的请求的支持只会是一个错误。换句话说,它可以非常有意地表明提供者并不意味着它从前端 JavaScript 代码中使用(问题中引用的 GitHub URL 似乎就是这种情况)。