AngularJS中CORS POST请求失败,Ajax请求却正常的问题求助
首先,咱们来拆解你遇到的问题:你用AngularJS发送跨域POST时遇到的Request header field Authorization is not allowed by Access-Control-Allow-Headers错误,核心原因是AngularJS的$http服务会合并全局默认请求头与当前请求的头配置,而你用undefined试图移除头的方式并不生效,反而触发了不符合服务器CORS规则的预检请求;而jQuery Ajax默认不会带上这些额外头,所以能正常工作。
先搞懂AngularJS HTTP请求的头处理机制
AngularJS的$http服务会自动把$http.defaults.headers里的全局头,和你在单个请求里配置的headers合并。这里有个容易踩坑的点:如果你在请求里把某个头设为undefined,它不会删除这个头,而是会把这个头的值设为字符串"undefined"。
你之前配置了全局的Authorization和Auth-Token头,虽然在获取token的请求里把它们设为undefined,但实际发送的请求还是会带上这两个头(值是"undefined")。这就触发了CORS的预检请求(OPTIONS方法),因为请求包含了自定义头,而服务器的Access-Control-Allow-Headers配置里没有包含这两个头,所以预检失败,返回了你看到的错误。
而jQuery的$.ajax在你没显式指定这些头的时候,不会自动带上它们,所以请求里只有Content-Type(你设置的application/json),服务器的CORS配置允许这个头,所以能顺利通过预检。
解决办法
1. 针对单个请求移除指定头(推荐)
在AngularJS里,把请求头设为null会移除该头,而不是设为undefined。修改你的请求代码如下:
$http({ method: 'POST', url: getAccessTokenUrl, data: clientdata, headers: { 'Authorization': null, 'Auth-Token': null } }).then(function(res){ console.log(res); }, function(err){ console.log(err); });
这样就能确保这两个头不会出现在请求里,避免触发不必要的预检,或者即使触发,请求里的头也符合服务器的CORS规则。
2. 临时修改全局头后恢复
如果这个获取token的请求是个特例,你可以在发起请求前临时移除全局头,请求完成后再恢复:
// 先保存原来的全局头 var originalAuthToken = $http.defaults.headers.common['Auth-Token']; var originalAuthorization = $http.defaults.headers.common['Authorization']; // 移除全局的这两个头 delete $http.defaults.headers.common['Auth-Token']; delete $http.defaults.headers.common['Authorization']; $http({ method: 'POST', url: getAccessTokenUrl, data: clientdata }).then(function(res){ console.log(res); }, function(err){ console.log(err); }).finally(function() { // 请求完成后恢复原来的全局头 if (originalAuthToken) { $http.defaults.headers.common['Auth-Token'] = originalAuthToken; } if (originalAuthorization) { $http.defaults.headers.common['Authorization'] = originalAuthorization; } });
3. 调整服务器端CORS配置(可选)
如果你有权限修改服务器的CORS配置,可以在Access-Control-Allow-Headers里添加Authorization和Auth-Token,这样即使请求带上这些头,服务器也会允许。不过如果这个请求确实不需要这两个头,前面的方法更合理,能减少不必要的请求头。
内容的提问来源于stack exchange,提问作者Aloke Kantal

