AngularJS $http POST withCredentials 失败,请求正文中有数据
Posted
技术标签:
【中文标题】AngularJS $http POST withCredentials 失败,请求正文中有数据【英文标题】:AngularJS $http POST withCredentials fails with data in request body 【发布时间】:2014-04-17 19:38:51 【问题描述】: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;
上面的代码可以正常工作:
当我在上面的 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(...
上述代码在预光照请求中失败:
看起来服务器启动了一个新会话,因为会话 cookie 由于某种原因没有发送。无论如何,我觉得我错过了一些非常简单的东西,一些标题或类似的东西...... 任何想法表示赞赏。提前致谢。
【问题讨论】:
好像是跨域调用的问题。 AJAX 调用仅在您调用的 url 与调用脚本位于同一域时发送 Cookie。 是的,绝对是 CORS 调用。它一直有效,直到您将正文添加到请求中... 【参考方案1】:阿米尔,
请允许我帮助您和其他人清楚地了解处理 CORS 时的预期内容,例如:
索引:
简单的 CORS 版本 预检 CORS 版本 带有凭据的请求简单 CORS 版本
-
您可以使用 GET、HEAD 或 POST:
在任何方法情况下,您不能设置自定义标头。
您始终可以让服务器端通过 Access-Control-Allow-Origin 标头限制域访问。
如果 POST 有请求数据:
Content-Type 必须是以下之一:
application/x-www-form-urlencoded
多部分/表单数据
文本/html
这个简单的版本显然不是你的情况......
预检 CORS 版本
-
您可以使用 GET、HEAD 或 POST:
在任何方法情况下,您可以设置自定义标头。
您始终可以让服务器端通过 Access-Control-Allow-Origin 标头限制域访问。
如果 POST 有请求数据:
Content-Type 可以是以下各项:
application/x-www-form-urlencoded
多部分/表单数据
文本/html
Content-Type 也可以是的其他类型:
应用程序/json
应用程序/xml
文本/xml
等
这个 PREFLIGHTED 版本显然是你的情况......
带有凭据的请求
-
如果您使用 cookies 进行调用,您需要在请求中设置以下参数部分:
withCredentials = true
带有凭据的请求显然也是您的情况......
【讨论】:
【参考方案2】:根据Cross-Origin Request with Preflight specs 凭据,即会话 cookie,不会在预检请求中发送,因此解决方案是在 REST 服务器端禁用 OPTIONS 请求的安全性,并仅允许 OPTIONS 请求没有会话 cookie 的请求。
当然要注意不要禁用 POST 和 GET 请求的安全性。
【讨论】:
【参考方案3】:根据https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
为了在 POST 中允许 cookie,需要使用 Access-Control-Allow-Credentials 配置远程:true。
如果你使用码头,你需要配置
<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 内容。
【讨论】:
以上是关于AngularJS $http POST withCredentials 失败,请求正文中有数据的主要内容,如果未能解决你的问题,请参考以下文章
Angularjs `$http` 发送 POST 而不是 GET