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


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

预检OPTIONS请求很好:

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启动chrome,一切正常。


898
2018-05-05 15:36


起源

您对“真实”请求(不是CORS pre-flight)的请求标头有哪些?我遇到了一个非常类似的问题。你有机会解决它吗? - vrutberg
看起来Chromium中的这个错误报告可能是相关的 code.google.com/p/chromium/issues/detail?id=237490 - vrutberg
@vrutberg是的,它看起来完全一样。而且它 有时 作品。例如,msdn测试 samples.msdn.microsoft.com/ietestcenter/CORS/CORS_014.htm 通过Chrome和FF传递。我的一个朋友拿了完全相同的代码并放在他的服务器上,它不起作用! twinspect.net/cors.htm - galadog
@vrutberg到目前为止我还没有解决这个问题:( - galadog
你有这方面的进展吗?我不再认为这与我之前提到的错误报告中描述的问题完全相同。如果我避免发出预检请求,它对我有用。错误报告根本没有提到预检请求。我无法在Chromium或Firefox的bug追踪器中找到关于此的确切错误报告。 - vrutberg


答案:


我也一直在努力解决这个问题。看来,规范禁止对预先发出的CORS请求进行3xx重定向。

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

从规格:

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

... 3。这是 实际要求。应用make a request步骤并观察   该 请求规则 在提出请求时如下。

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

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

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

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

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

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

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

(重点来自文件。)

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


14
2017-12-31 09:12



注意当前的CORS规范,它是其中的一部分 fetch.spec.whatwg.org,现在允许在预检后遵循重定向。有关详细信息,请参阅答案 stackoverflow.com/questions/34949492/... - sideshowbarker


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

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

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

  3. 跟踪客户端(即XMLHttpRequest)是否实际请求
    凭证首先发送。当一个         同源请求重定向到原始的不同来源         请求将发送cookie,无论是否请求,因为它是         同源。新的跨源请求不应发送cookie         除非他们被请求,否则访问控制检查         如果服务器被授予,响应将成功         “访问控制允许来源= *”。


1
2018-06-21 10:35



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