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

Posted

技术标签:

【中文标题】为啥浏览器不遵循使用 XMLHTTPRequest 和 CORS 的重定向?【英文标题】:Why browser do not follow redirects using XMLHTTPRequest and CORS?为什么浏览器不遵循使用 XMLHTTPRequest 和 CORS 的重定向? 【发布时间】:2013-04-29 11:09:23 【问题描述】:

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

预检选项请求很好:

Request Method:OPTIONS
Status Code:200 OK

请求标头

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

响应标头

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

那么实际请求在收到303后就停止了:

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

响应标头:

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

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

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

【问题讨论】:

“真实”请求(不是 CORS 飞行前)的请求标头是什么?我遇到了一个非常相似的问题。你有没有偶然解决它? 看起来这个 Chromium 中的错误报告可能与 code.google.com/p/chromium/issues/detail?id=237490 相关 @vrutberg 是的,它看起来一模一样。此外,它有时有效。例如,一个 msdn 测试 samples.msdn.microsoft.com/ietestcenter/CORS/CORS_014.htm 在 Chrome 和 FF 中都通过了。我的一个朋友把完全相同的代码放在他的服务器上,但它不起作用! twinspect.net/cors.htm @vrutberg 到目前为止我还没有解决这个问题:( 你在这方面有什么进展吗?我不再认为这与我之前提到的错误报告中描述的问题完全相同。如果我避免发出预检请求,它对我有用。错误报告根本没有提到预检请求。我无法在 Chromium 或 Firefox 的错误跟踪器中找到准确的错误报告。 【参考方案1】:

我也一直在努力解决这个问题。规范似乎禁止预检 CORS 请求的 3xx 重定向。

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

来自规范:

(第 1 步和第 2 步。详细说明预检过程。然后我们来到步骤...)

...3。这是实际要求。应用发出请求的步骤并观察 请求规则在发出请求时。

如果响应的 HTTP 状态代码为 301、302、303、307 或 308 申请cache and network error steps。

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

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

注意:这对用户凭据的设置没有影响。 IE。如果块 cookie 标志未设置,cookie 将由响应设置。

每当应用缓存和网络错误步骤时,请遵循这些 步骤:

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

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

(重点来自文档。)

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

【讨论】:

请注意,当前的 CORS 规范是 fetch.spec.whatwg.org 的一部分,现在允许在预检后进行重定向。更多详细信息,请参阅***.com/questions/34949492/…的答案【参考方案2】:

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

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

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

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

【讨论】:

我相信他的问题不涉及同源请求。这是一个具有 302 响应的跨域请求。

以上是关于为啥浏览器不遵循使用 XMLHTTPRequest 和 CORS 的重定向?的主要内容,如果未能解决你的问题,请参考以下文章

不使用本机 XMLHttpRequest 的原因 - 为啥 $.ajax 是强制性的?

并行文件上传 XMLHttpRequest 请求以及为啥它们不起作用

为啥一些跨域 XMLHttpRequest 请求不返回 CORS 错误

为啥 XMLHttpRequest 上传在 Firefox 中没有正确失败?

为啥我使用xmlhttprequest抓取数据时主键跳转量大?

为啥叫 XMLHttpRequest?