javascript - 由于 CORS,HTTP 身份验证请求在浏览器中失败,在 Node 中正常

标签 javascript cors xmlhttprequest node-request request-promise

我一直在尝试诊断一个问题,即使用 HTTP Basic Auth 的 GET 请求在 Node 中成功,但在浏览器中失败。该问题直接表现为 CORS 故障(401 页面上没有 Access-Control-Allow-Origin)。

request.js:119 OPTIONS http://HOST?PARAMS 401 (Unauthorized)
ClientRequest._onFinish @ request.js:119
(anonymous) @ request.js:61
...

17:53:59.170 localhost/:1 Failed to load http://HOST?PARAMS: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9966' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

请求看起来像这样:

const request = require("request-promise");
const options = {"url":"http://...?","auth":{"user":"...","pass":"..."},"json":true,"qs":{...},"headers":{},"resolveWithFullResponse":true}
request.get(options).then(...);

此请求在 Chrome 中的显示方式:

enter image description here

这里让我感到惊讶的是:

  • 方法是 OPTIONS,不是 GET。 (我没有明确要求。)
  • 我的身份验证凭据未包含在 header 中(即使我没有设置 sendImmediately: false
  • “显示临时 header ”警告。

我想知道的:

  • 这是预期的行为吗?
  • 如果不是,出了什么问题?
  • 如果是,出了什么问题? :)

在命令行上运行等效的请求似乎工作正常:

curl -I 'http://MYUSERNAME:MYPASSWORD@SAMEURL?SAME=PARAMETERS' -H 'Origin: http://localhost:4466' -X OPTIONS
HTTP/1.1 200 OK
Date: Wed, 20 Jun 2018 07:29:28 GMT
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: http://localhost:4466
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials
Vary: Origin
X-Frame-Options: SAMEORIGIN
Allow: GET,HEAD,POST,OPTIONS
Content-Length: 0

但是我注意到,如果 URL 中没有提供凭据,响应中就没有 CORS header :

HTTP/1.1 401 Unauthorized
Date: Wed, 20 Jun 2018 07:45:26 GMT
Server: Apache/2.4.29 (Unix) OpenSSL/1.0.2l
WWW-Authenticate: Basic realm="Authentication Required"
Content-Length: 381
Content-Type: text/html; charset=iso-8859-1

这是正确的行为吗?

假设

我怀疑:

  • 浏览器正在发送 OPTIONS“飞行前”请求,因为它必须这样做,因为该请求不是“简单请求”。 (不清楚这是请求库还是浏览器本身做的)
  • 服务器响应 401,因为未提供凭据,但没有添加它应该添加的 CORS header 。
  • 如果没有 CORS header ,浏览器会阻止请求库访问结果,因此无法完成身份验证。

我不确定的是:

  • 服务器是否配置错误?
  • Request 是否未能在 OPTIONS 预检请求中传递凭据?

最佳答案

服务器配置错误。它没有正确启用 CORS。要正确启用 CORS,它必须使用 200204 状态代码响应未经身份验证的 OPTIONS 请求。

Request 并非“未能”在 OPTIONS 预检请求中传递凭据。 Request 甚至没有发出 OPTIONS 请求。相反,浏览器引擎是独立的。

并且在您自己的代码中为请求指定凭据标志不会导致将凭据添加到预检 OPTIONS 请求中。相反,凭据只会从您自己的代码添加到 GET 请求中——也就是说,如果预检成功并且浏览器实际上曾经继续发出该 GET 请求。

这是因为 Fetch 规范中的 CORS 协议(protocol)要求规定浏览器必须忽略预检 OPTIONS 请求中的所有凭据。

参见 https://fetch.spec.whatwg.org/#ref-for-credentials%E2%91%A5 :

a CORS-preflight request never includes credentials

因此,您遇到的行为是有意设计的。

有关更详细的相关解释,请参阅 HTTP status code 401 even though I’m sending credentials in the request 处的答案。 .

关于javascript - 由于 CORS,HTTP 身份验证请求在浏览器中失败,在 Node 中正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50942883/

相关文章:

aws-lambda - API 网关 : Can't Enable CORS

javascript - XMLHttpRequest onprogress total 在 Chrome 上始终为 0

javascript - 如何获取远程图像以在 Canvas 中显示?

javascript - 如何使用 dynamoose 跳过、排序和限制?

javascript - 在推送项目之前检查属性值是否存在

javascript - 405 方法不允许使用 Tomcat

javascript - 将插入符号位置保持在文本输入中的可见位置 - firefox 行为不当

angularjs - Web Api 2 和 Angular 之间的 CORS 错误

json - 使用 xmlhttp 的经典 ASP 页面可以发出 JSON 请求吗?

javascript - 如何通过点击XPage上的按钮将附件内容读取到数组或字符串中?