12

我正在使用 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,一切正常。

4

2 回答 2

16

我也一直在为此苦苦挣扎。规范似乎禁止预检 CORS 请求的 3xx 重定向。

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

从规范:

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

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

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

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

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

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

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

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

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

(重点来自文档。)

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

于 2013-12-31T09:12:41.177 回答
2

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

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

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

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

于 2013-06-21T10:35:11.347 回答