javascript 为什么浏览器不遵循使用 XMLHTTPRequest 和 CORS 的重定向?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16386148/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 04:26:52  来源:igfitidea点击:

Why browser do not follow redirects using XMLHTTPRequest and CORS?

javascriptajaxgoogle-chromerestcors

提问by galadog

I am writing a web application for some service using RESTful API. The API is available at https://api.exampleand app at https://app.example. Simple GET requests using CORS are working just fine in Chrome and Firefox. Some method accept data via POST and return 303 code with new uri in Location header.

我正在使用 RESTful API 为某些服务编写 Web 应用程序。该 API 可在https://api.example和应用程序在https://app.example。使用 CORS 的简单 GET 请求在 Chrome 和 Firefox 中运行良好。某些方法通过 POST 接受数据并在 Location 标头中返回带有新 uri 的 303 代码。

Preflight OPTIONS request is fine:

预检选项请求很好:

Request Method:OPTIONS
Status Code:200 OK

Request Headers

请求头

Accept:*/*
Accept-Charset:UTF-8,*;q=0.5
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,ru;q=0.6
Access-Control-Request-Headers:origin, authorization, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
DNT:1
Host:api.example
Origin:https://app.example
Referer:https://app.example/app/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.32 (KHTML, like Gecko) Chrome/27.0.1425.0 Safari/537.32 SUSE/27.0.1425.0

Response Headers

响应头

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Authorization, Content-Type
Access-Control-Allow-Methods:GET,POST,PUT,DELETE,HEAD,OPTIONS
Access-Control-Allow-Origin:https://app.example
Access-Control-Expose-Headers:*
Access-Control-Max-Age:3628800
Connection:keep-alive
Content-Length:0
Date:Sun, 05 May 2013 15:22:50 GMT
Server:nginx/1.2.5

Then the actual request just stop after receiving 303:

然后实际请求在收到 303 后才停止:

Request URL:https://api.example
Request Method:POST
Status Code:HTTP/1.1 303 See Other

Response headers:

响应头:

Server:nginx/1.2.5
Location:https://api.example/some_url
Date:Sun, 05 May 2013 15:27:49 GMT
Content-Type:application/json
Content-Length:0
Connection:keep-alive
Access-Control-Max-Age:3628800
Access-Control-Expose-Headers:*
Access-Control-Allow-Origin:https://app.example
Access-Control-Allow-Methods:GET,POST,PUT,DELETE,HEAD,OPTIONS
Access-Control-Allow-Headers:Authorization, Content-Type
Access-Control-Allow-Credentials:true

By RFC user agent should follow redirects, but Chrome and FF seems doesn't behave as expected. Is it a browsers' bug or I am doing something wrong?

通过 RFC 用户代理应该遵循重定向,但 Chrome 和 FF 似乎没有按预期运行。是浏览器的错误还是我做错了什么?

update:If I start chromium with --disable-web-security everything works fine.

更新:如果我使用 --disable-web-security 启动铬,一切正常。

回答by nothankyou

I've been wrestling with this, too. It appears that 3xx redirects for preflighted CORS requests are forbidden by the spec.

我也一直在纠结这个。规范似乎禁止预检 CORS 请求的 3xx 重定向。

http://www.w3.org/TR/cors/

http://www.w3.org/TR/cors/

From the spec:

从规范:

(Step 1. and 2. detail the preflighting process. And the we come to step...)

(第 1 步和第 2 步详细说明预检过程。然后我们就开始……)

...3. This is the actual request. Apply the make a request steps and observe the request rulesbelow while making the request.

If the response has an HTTP status code of 301, 302, 303, 307, or 308Apply the cache and network error steps.

...3. 这是实际的请求。应用发出请求步骤并在发出请求时遵守以下请求规则

如果响应的 HTTP 状态代码为 301、302、303、307 或 308,请应用缓存和网络错误步骤

And then if we scroll on down to http://www.w3.org/TR/cors/#cache-and-network-error-steps:

然后如果我们向下滚动到http://www.w3.org/TR/cors/#cache-and-network-error-steps

Whenever the network error stepsare applied, terminate the algorithm that invoked this set of steps and set the cross-origin request status to network error.

Note: This has no effect on setting of user credentials. I.e. if the block cookies flag is unset, cookies will be set by the response.

Whenever the cache and network error stepsare applied, follow these steps:

Remove the entries in the preflight result cache where origin field value is a case-sensitive match for source origin and url field value is a case-sensitive match for request URL.

Apply the network error steps acting as if the algorithm that invoked the cache and network error steps invoked the network error steps instead.

每当应用网络错误步骤时,终止调用这组步骤的算法并将跨源请求状态设置为网络错误。

注意:这对用户凭据的设置没有影响。即,如果未设置阻止 cookie 标志,则响应将设置 cookie。

每当应用缓存和网络错误步骤时,请执行以下步骤:

删除预检结果缓存中的条目,其中源字段值是源源的区分大小写匹配,而 url 字段值是请求 URL 的区分大小写匹配。

应用网络错误步骤,就像调用缓存的算法和网络错误步骤调用网络错误步骤一样。

(Emphasis taken from the doc.)

(重点来自文档。)

3xx redirects are, however, permitted for simple CORS requests.

但是,对于简单的 CORS 请求,允许 3xx 重定向。

回答by Jo?o Beir?o

If its the chromium bug here is the possible errors on your code given by chromium suport:

如果它的铬错误是铬支持给出的代码中可能的错误:

  1. If a same-origin request causes a redirect to a different origin,
    do not enforce access control checks for the redirect response
    itself, because the request which resulted in the redirect was
    same-origin.

  2. If a same-origin request causes a redirect to a different origin,
    use the original request's URL as the origin for the new request do not use a unique security origin.

  3. Track whether the client (i.e., XMLHttpRequest) actually requested
    that credentials be sent in the first place. When a same-origin request redirects to a different origin, the original request will send cookies whether requested or not, because it is same-origin. The new cross-origin request should not send cookies unless they were requested, so that the access control checks on the response will succeed if the server granted "Access-Control-Allow-Origin=*".

  1. 如果同源请求导致重定向到不同的源,
    不要对重定向响应
    本身强制执行访问控制检查,因为导致重定向的请求是
    同源的。

  2. 如果同源请求导致重定向到不同的源,请
    使用原始请求的 URL 作为新请求的源,不要使用唯一的安全源。

  3. 首先跟踪客户端(即 XMLHttpRequest)是否确实请求
    发送凭据。当同源请求重定向到不同的源时,无论是否请求,原始请求都会发送 cookie,因为它是同源的。除非被请求,否则新的跨域请求不应发送 cookie,以便如果服务器授予“Access-Control-Allow-Origin=*”,则对响应的访问控制检查将成功。