XmlHttpRequest CORS POST发送时没有Cookie



我有一个Rails服务,为我的AngularJS前端应用程序返回数据。该服务被配置为通过返回足够的报头来允许CORS请求。

当我发出接收数据的GET请求时,会发送CORS标头,以及我之前在登录时收到的会话cookie,您可以自己看到:

Request URL:http://10.211.194.121:3000/valoradores
Request Method:GET
Status Code:200 OK
Request Headers
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Cookie:_gestisol_session=BAh7B0kiDHVzZXJfaWQGOgZFRmkASSIPc2Vzc2lvbl9pZAY7AEZJIiVmYTg3YTIxMjcxZWMxNjZiMjBmYWZiODM1ODQzMjZkYQY7AFQ%3D--df348feea08d39cbc9c817e49770e17e8f10b375
Host:10.211.194.121:3000
Origin:http://10.211.194.121:8999
Pragma:no-cache
Referer:http://10.211.194.121:8999/
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36
X-Requested-With:XMLHttpRequest
Response Headers
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:X-Requested-With,X-Prototype-Version,Content-Type,Cache-Control,Pragma,Origin
Access-Control-Allow-Methods:GET,POST,OPTIONS
Access-Control-Allow-Origin:http://10.211.194.121:8999
Access-Control-Max-Age:1728000
Cache-Control:max-age=0, private, must-revalidate
Connection:Keep-Alive
Content-Length:5389
Content-Type:application/json; charset=utf-8
Date:Mon, 04 Nov 2013 14:30:51 GMT
Etag:"2470d69bf6db243fbb337a5fb3543bb8"
Server:WEBrick/1.3.1 (Ruby/1.9.3/2011-10-30)
X-Request-Id:15027b3d323ad0adef7e06103e5aa3a7
X-Runtime:0.017379
X-Ua-Compatible:IE=Edge

一切都很好,我拿回了我的数据。

但是,当我发出POST请求时,CORS头和会话cookie都不会随请求一起发送,并且POST在服务器上被取消,因为它没有会话标识符。这些是请求的标题:

Request URL:http://10.211.194.121:3000/valoraciones
Request Headers
Accept:application/json, text/plain, */*
Cache-Control:no-cache
Content-Type:application/json;charset=UTF-8
Origin:http://10.211.194.121:8999
Pragma:no-cache
Referer:http://10.211.194.121:8999/
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payload
{valoracione:{revisiones_id:1, valoradores_id:1}}
valoracione: {revisiones_id:1, valoradores_id:1}

并且该服务以403回答,因为该请求不包含会话cookie。

我不知道POST请求失败的原因,因为$resource的配置与另一个一样,并且我已经定义了$httpProvider发送凭据的默认值(GET请求成功时它就可以工作(:

  .config(['$httpProvider', function($httpProvider) {
     $httpProvider.defaults.withCredentials = true;
    }])

当我在实例上调用$save((时,这是失败的资源:

'use strict';
angular.module('gestisolApp')
  .service('ValoracionesService', ['$resource', 'API_BASE_URL', function ValoracionesService($resource, API_BASE_URL) {
    this.valoraciones = $resource(API_BASE_URL + '/valoraciones');
  }]);

这是成功调用query((的服务:

'use strict';
angular.module('gestisolApp')
  .service('ValoradoresService', ['$resource', 'API_BASE_URL', function ValoradoresService($resource, API_BASE_URL) {
    this.valoradores = $resource(API_BASE_URL + '/valoradores');
  }]);

他们很像。

有人知道为什么POST是在没有会话cookie的情况下发送的吗?

编辑

为了完成信息,飞行前通过以下方法进行处理,并且处理正常,因为失败的POST之前的请求是一个OPTIONS,它以200响应代码成功:

def cors_preflight_check
        headers['Access-Control-Allow-Origin'] = 'http://10.211.194.121:8999'
        headers['Access-Control-Allow-Methods'] = 'GET,POST,OPTIONS'
        headers['Access-Control-Allow-Headers'] = 'X-Requested-With,X-Prototype-Version,Content-Type,Cache-Control,Pragma,Origin'
        headers['Access-Control-Allow-Credentials'] = 'true'
        headers['Access-Control-Max-Age'] = '1728000'
        render :nothing => true, :status => 200, :content_type => 'text/html'
end

这是故障POST之前的CORS OPTIONS请求/响应交换:

Request URL:http://10.211.194.121:3000/valoraciones
Request Method:OPTIONS
Status Code:200 OK
Request Headers
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, x-requested-with, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:10.211.194.121:3000
Origin:http://10.211.194.121:8999
Referer:http://10.211.194.121:8999/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36
Response Headers
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:X-Requested-With,X-Prototype-Version,Content-Type,Cache-Control,Pragma,Origin
Access-Control-Allow-Methods:GET,POST,OPTIONS
Access-Control-Allow-Origin:http://10.211.194.121:8999
Access-Control-Max-Age:1728000
Cache-Control:max-age=0, private, must-revalidate
Connection:Keep-Alive
Content-Length:1
Content-Type:text/html; charset=utf-8
Date:Mon, 04 Nov 2013 15:57:38 GMT
Etag:"7215ee9c7d9dc229d2921a40e899ec5f"
Server:WEBrick/1.3.1 (Ruby/1.9.3/2011-10-30)
X-Request-Id:6aa5bb4359d54ab5bfd169e530720fa9
X-Runtime:0.003851
X-Ua-Compatible:IE=Edge

编辑2:我更改了标题以清楚地反映我的问题

我遇到了类似的问题,在angular$http CORS请求解决问题之前添加了以下内容。$http.defaults.withCredentials=true;

请参阅https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Requests_with_credentials了解更多详细信息。

当涉及CORS时,浏览器将在POST请求之前发送OPTIONS请求。

我不知道Rails的具体情况,但我想您必须配置Rails,以便使用足够的CORS头来实际响应OPTIONS请求。

下面的代码只是为了进行比较,它显示了如何在Java中解决这个问题:

public void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setHeader("Access-Control-Allow-Origin", "http://10.211.194.121:8999");
    resp.setHeader("Access-Control-Allow-Credentials", "true");
    resp.setHeader("Access-Control-Allow-Methods", "OPTIONS, POST, GET");
    resp.setHeader("Access-Control-Allow-Headers", "X-Requested-With,X-Prototype-Version,Content-Type,Cache-Control,Pragma,Origin");
    resp.setHeader("Access-Control-Max-Age", "600");
    resp.setHeader("Access-Control-Expose-Headers","Access-Control-Allow-Origin");
    super.doOptions(req, resp);
}

但它可能会让你走上正确的轨道,如何在Rails中配置它。

好吧,我终于弄清楚发生了什么。

根据这个问题的答案,我从cookie中删除了HttpOnly参数,并使其在Firefox上运行。Chrome的后期只是应用答案中的其余建议来使其发挥作用,比如为cookie设置域。

最新更新