CORS pre-flight返回Access-Control-Allow-Origin:*,浏览器仍然失败请求

时间:2013-08-01 20:10:56

标签: javascript node.js express cors jqxhr

触发AJAX GEThttp://qualifiedlocalhost:8888/resource.json启动预期的CORS飞行前,看起来它正确回归:

行前OPTIONS请求

Request URL:http://qualifiedlocalhost:8888/resource.json
Request Method:OPTIONS
Status Code:200 OK

请求标题

Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, origin, x-requested-with
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:qualifiedlocalhost:8888
Origin:http://localhost:9000
Pragma:no-cache
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36

响应标头

Access-Control-Allow-Headers:Content-Type, X-Requested-With
Access-Control-Allow-Methods:GET,PUT,POST,DELETE
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:2
Content-Type:text/plain
Date:Thu, 01 Aug 2013 19:57:43 GMT
Set-Cookie:connect.sid=s%3AEpPytDm3Dk3H9V4J9y6_y-Nq.Rs572s475TpGhCP%2FK%2B2maKV6zYD%2FUg425zPDKHwoQ6s; Path=/; HttpOnly
X-Powered-By:Express

看起来不错?

所以它应该有效,对吧?

但后续请求仍然失败,错误为XMLHttpRequest cannot load http://qualifiedlocalhost:8888/resource.json. Origin http://localhost:9000 is not allowed by Access-Control-Allow-Origin.

真实请求

Request URL:http://qualifiedlocalhost:8888/resource.json

请求标题

Accept:application/json, text/plain, */*
Cache-Control:no-cache
Origin:http://localhost:9000
Pragma:no-cache
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36
X-Requested-With:XMLHttpRequest

帮助!

也许它正盯着我。但是,任何想法?以防它是相关的...我正在使用AngularJS $resource并与CompoundJS服务器通信。

6 个答案:

答案 0 :(得分:13)

更改您的Access-Control-Allow-Methods:'GET,POST'到'GET,POST,PUT,DELETE'

之前:

   app.use(function(req, res, next) {
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
        next();
    });

后:

app.use(function(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
    next();
});

答案 1 :(得分:7)

recently had the same issue。问题是Access-Control-Allow-Origin标题(以及,如果您使用它,Access-Control-Allow-Credentials标题)必须在两者预检响应和实际响应中发送。

你的例子只在预检响应中有它。

答案 2 :(得分:6)

您的Web服务器/获取功能是否还包括HTTP标头:Access-Control-Allow-Origin?我最终使用AngularJS 1.0.7和远程Java servlet获得了成功。这是我的Java代码片段 - AngularJS客户端不需要进行任何更改:

的Servlet

@Override
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // Send Response
    super.doOptions(request,  response);
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With");
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /* ... */
    response.setHeader("Access-Control-Allow-Origin", "*");
}

更优雅的替代方案是servlet过滤器。

答案 3 :(得分:3)

我们一直注意到同样的问题,即服务器发送正确的CORS头,但浏览器失败,因为它认为没有满足CORS要求。更有趣的是,在我们的例子中,它只发生在同一浏览器会话中的一些AJAX调用上,但不是全部。

工作理论......

清除浏览器缓存解决了我们案例中的问题 - 我当前的工作原理是这与跨源服务器设置的cookie有关。我注意到在你的场景中,有一个cookie被设置为对飞行前OPTIONS请求的响应的一部分。您是否尝试过让服务器不为来自其他来源的请求设置任何cookie?

但是,我们注意到在某些情况下,重置浏览器后问题再次出现。此外,在私有模式下运行浏览器会导致问题消失,指出与浏览器缓存中的内容有关的一些问题。

作为参考,这是我的场景(我几乎在SO中发布了这个新问题,但是把它放在这里):

我们遇到了一个错误,其中通过jQuery.ajax发出的一些 CORS GET请求失败了。在给定的浏览器会话中,我们看到飞行前OPTIONS请求经过,然后是实际请求。在同一个会话中,一些请求通过而其他请求失败。

浏览器网络控制台中的请求和响应序列如下所示:

首先是OPTIONS转航前请求

OPTIONS /api/v1/users/337/statuses
HTTP/1.1 Host: api.obfuscatedserver.com 
Connection: keep-alive 
Access-Control-Request-Method: GET 
Origin: http://10.10.8.84:3003 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Access-Control-Request-Headers: accept, origin, x-csrf-token, auth 
Accept: */* Referer: http://10.10.8.84:3003/ 
Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8

得到的反应如,

HTTP/1.1 200 OK 
Date: Tue, 06 Aug 2013 19:18:22 GMT 
Server: Apache/2.2.22 (Ubuntu) 
Access-Control-Allow-Origin: http://10.10.8.84:3003 
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT 
Access-Control-Max-Age: 1728000 
Access-Control-Allow-Credentials: true 
Access-Control-Allow-Headers: accept, origin, x-csrf-token, auth 
X-UA-Compatible: IE=Edge,chrome=1 
Cache-Control: no-cache 
X-Request-Id: 4429c4ea9ce12b6dcf364ac7f159c13c 
X-Runtime: 0.001344 
X-Rack-Cache: invalidate, pass 
X-Powered-By: Phusion 
Passenger 4.0.2 
Status: 200 OK 
Vary: Accept-Encoding
Content-Encoding: gzip

然后是实际的GET请求,

GET https://api.obfuscatedserver.com/api/v1/users/337
HTTP/1.1 
Accept: application/json, text/javascript, */*; q=0.01 
Referer: http://10.10.8.84:3003/ 
Origin: http://10.10.8.84:3003 
X-CSRF-Token: xxxxxxx 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 
auth: xxxxxxxxx

在浏览器控制台中出现错误,例如

XMLHttpRequest
  cannot load https://api.obfuscatedserver.com/api/v1/users/337.
  Origin http://10.10.8.84:3003 is not allowed by Access-Control-Allow-Origin.

其他调试

我可以通过curl重播相同的序列,我看到来自服务器的有效响应。即他们有预期的CORS标题,应该让请求通过。

在私人/隐身浏览器窗口中运行相同的方案并未重现问题。这导致我尝试清除缓存,这也使问题消失了。但过了一会儿,它回来了。

问题出现在iPhone safari以及OSX桌面上的Chrome上。

我真正需要帮助

我怀疑在跨域域中设置了一些cookie,这些cookie在这里涉及并可能暴露浏览器中的错误。我可以在浏览器中设置工具或断点(本机堆栈?)来尝试进一步调试吗?代码中用于评估CORS策略的断点是理想的。

答案 4 :(得分:0)

看起来您对“选项”的回复工作正常。问题似乎在于“获得”回应。

您希望让'get'响应返回与'options'响应相同的CORS标头。

特别是,“获取”响应应包括

Access-Control-Allow-Headers:Content-Type, X-Requested-With
Access-Control-Allow-Methods:GET,PUT,POST,DELETE
Access-Control-Allow-Origin:*

答案 5 :(得分:0)

使用cors模块来避免问题

var cors = require('cors')

var app = express()
app.use(cors())