javascript – 由于CORS,在浏览器中HTTP Auth请求失败,在Node中确定

我试图诊断一个问题,即使用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. (我没有明确要求.)
>我的身份验证凭据未包含在标头中(即使我没有设置sendImmediately:false
>显示“临时标题”警告.

我想知道的是:

>这是预期的行为吗?
>如果没有,出了什么问题?
>如果是的话,会出现什么问题? 🙂

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

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头:

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头.
>如果没有CORS标头,浏览器会阻止请求库访问结果,因此无法完成身份验证.

我不确定的是什么:

>服务器配置错误了吗?
>请求无法在OPTIONS预检请求中传递凭据吗?

最佳答案
服务器配置错误.它没有正确启用CORS.要正确启用CORS,它必须使用200或204状态代码响应未经身份验证的OPTIONS请求.

请求不会“失败”传递OPTIONS预检请求中的凭据.请求甚至没有发出OPTIONS请求.而是浏览器引擎本身.

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

这是因为Fetch中的CORS协议要求指定浏览器必须省略预检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 an Authorization request header的答案.

转载注明原文:javascript – 由于CORS,在浏览器中HTTP Auth请求失败,在Node中确定 - 代码日志