AngularJS $ http POST withCredentials失败,请求正文中包含数据

时间:2014-03-13 07:57:17

标签: rest session-cookies cors preflight angularjs-http

AngularJS使用REST对服务器端进行身份验证,并获取JSESSIONID cookie。 在下一步中,我尝试使用REST从服务器端获取一些JSON数据以及在上一步中获得的会话cookie。这是客户端代码:

getSomeJSONDataFromServer:function() {
var deferred = $q.defer();
$http({
    method: 'POST',
    withCredentials: true,
    url: "http://domain.name/app/someURL",
    headers:{
        'Accept':'application/json',
        'Content-Type':'application/json; charset=utf-8',
        'Access-Control-Request-Headers': 'X-Requested-With, content-type, accept, origin, withcredentials'
    }
})
.success(function(data, status, headers, config) {
    // handle data
})
.error(function(data, status, headers, config) {
    // handle error
});
return deferred.promise;
}

上面的代码工作正常:

CORS $http request without body

当我在上面的POST请求体中发送一些数据时,问题就开始了。

...
$http({
    method: 'POST',
    withCredentials: true,
    url: "http://domain.name/app/someURL",
    headers:{
        'Accept':'application/json',
        'Content-Type':'application/json; charset=utf-8',
        'Access-Control-Request-Headers': 'X-Requested-With, content-type, accept, origin, withcredentials'
    },
    data: '{}'
})
.success(...

上述代码在prelight请求中失败:

CORS $http request with body fails!

看起来服务器启动了一个新会话,因为会话cookie由于某种原因没有发送。无论如何,我觉得我错过了一些非常简单的东西,一些标题或类似的东西...... 任何想法都表示赞赏。提前谢谢。

3 个答案:

答案 0 :(得分:7)

阿米尔,

请允许我帮助您和其他人清楚地了解在处理CORS时的预期结果:

指数:

  • 简单的CORS版本
  • 预检CORS版本
  • 凭据凭据

简单CORS版本

  1. 您可以使用GET,HEAD或POST:
    • 在任何方法案例中,您 > <设置自定义标题
    • 您始终可以让服务器端通过Access-Control-Allow-Origin标头限制域访问。
  2. 如果POST有请求数据:
    • 内容类型必须以下任何一项:
      • 应用程序/ x-WWW窗体-urlencoded
      • 的multipart / form-data的
      • text / html的
  3.   

    这个简单的版本显然不是你的情况......

    预检CORS版本

    1. 您可以使用GET,HEAD或POST:
      • 在任何方法案例中,您 CAN 设置自定义标题
      • 您始终可以让服务器端通过Access-Control-Allow-Origin标头限制域访问。
    2. 如果POST有请求数据:
      • 内容类型可能以下内容:
        • 应用程序/ x-WWW窗体-urlencoded
        • 的multipart / form-data的
        • text / html的
      • 内容类型也可以其他类型:
        • 应用/ JSON
        • 应用/ XML
        • 文本/ XML
    3.   

      这个PREFLIGHTED版本显然是你的情况......

      凭证的请求

      1. 如果您使用 Cookie 调用来电,则需要在请求中设置以下参数部分:
        • withCredentials = true
      2.   

        使用凭证的请求显然也是您的理由......

答案 1 :(得分:2)

根据Cross-Origin Request with Preflight specs凭据(即会话cookie)未在预检请求中发送,因此解决方案是禁用REST服务器端的OPTIONS请求的安全性,并仅允许没有会话cookie的请求用于OPTIONS请求。

当然要小心不要禁用POST和GET请求的安全性。

答案 2 :(得分:0)

根据https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

为了在POST中允许cookie,需要使用Access-Control-Allow-Credentials配置远程:true。

如果您使用的是jetty,则需要配置

    <init-param>
        <param-name>allowCredentials</param-name>
        <param-value>true</param-value>
    </init-param>

引用MDN的文章,

重要说明:在响应凭证请求时,服务器必须指定域,并且不能使用通配符。如果标头被通配为:Access-Control-Allow-Origin:*,则上述示例将失败。由于Access-Control-Allow-Origin明确提及http://foo.example,因此凭据识别内容将返回到调用Web内容。