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

时间:2013-05-05 15:36:29

标签: javascript ajax google-chrome rest 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,一切正常。

2 个答案:

答案 0 :(得分:15)

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

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

来自规范:

(步骤1和2.详细说明了印前检查过程。我们步骤......)

  

... 3。这是实际请求。应用make a request步骤并观察   在发出请求时,请求规则

     

如果响应的HTTP状态代码为301,302,303,307或308   应用cache and network error steps

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

  

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

     

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

     

每当应用缓存和网络错误步骤时,请按照以下步骤操作   步骤进行:

     

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

     

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

(重点来自文档。)

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

答案 1 :(得分:1)

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

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

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

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