在下面的代码中,AngularJS $http方法调用URL,并提交xsrf对象作为“Request Payload”(在Chrome调试器网络选项卡中描述)。jQuery $。ajax方法做同样的调用,但提交xsrf作为“表单数据”。
如何让AngularJS将xsrf作为表单数据而不是请求有效载荷提交?
var url = 'http://somewhere.com/';
var xsrf = {fkey: 'xsrf key'};
$http({
method: 'POST',
url: url,
data: xsrf
}).success(function () {});
$.ajax({
type: 'POST',
url: url,
data: xsrf,
dataType: 'json',
success: function() {}
});
下面一行需要添加到传递的$http对象中:
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
并且传递的数据应该转换为url编码的字符串:
> $.param({fkey: "key"})
'fkey=key'
你会得到这样的结果:
$http({
method: 'POST',
url: url,
data: $.param({fkey: "key"}),
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
})
来自:https://groups.google.com/forum/ # !味精naedj1lyo0/4vj_72ezcdsj /角度/ 5
更新
要使用AngularJS V1.4中添加的新服务,请参见
只使用AngularJS服务的url编码变量
为post创建一个适配器服务:
services.service('Http', function ($http) {
var self = this
this.post = function (url, data) {
return $http({
method: 'POST',
url: url,
data: $.param(data),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
}
})
在你的控制器或其他地方使用它:
ctrls.controller('PersonCtrl', function (Http /* our service */) {
var self = this
self.user = {name: "Ozgur", eMail: null}
self.register = function () {
Http.post('/user/register', self.user).then(function (r) {
//response
console.log(r)
})
}
})
这并不是一个直接的答案,而是一个略有不同的设计方向:
不要将数据作为表单发布,而是作为JSON对象直接映射到服务器端对象,或者使用REST风格的路径变量
现在我知道这两个选项都不适合您的情况,因为您试图传递一个XSRF键。像这样把它映射成一个路径变量是一个糟糕的设计:
http://www.someexample.com/xsrf/{xsrfKey}
因为本质上你会想要传递xsrf密钥到其他路径,/login, /book-appointment等,你不想弄乱你漂亮的URL
有趣的是,将它作为对象字段添加也不合适,因为现在你传递给服务器的每个json对象都必须添加字段
{
appointmentId : 23,
name : 'Joe Citizen',
xsrf : '...'
}
您当然不希望在服务器端类上添加另一个与域对象没有直接语义关联的字段。
在我看来,传递xsrf密钥的最佳方式是通过HTTP报头。许多xsrf保护服务器端web框架库都支持这一点。例如,在Java Spring中,您可以使用X-CSRF-TOKEN头传递它。
Angular出色的将JS对象绑定到UI对象的能力意味着我们可以摆脱一起发布表单的做法,而是发布JSON。JSON可以很容易地反序列化为服务器端对象,并支持复杂的数据结构,如映射、数组、嵌套对象等。
如何在表单有效负载中发布数组?也许是这样的:
shopLocation=downtown&daysOpen=Monday&daysOpen=Tuesday&daysOpen=Wednesday
或:
shopLocation=downtwon&daysOpen=Monday,Tuesday,Wednesday
都是糟糕的设计。
AngularJS的做法是正确的,因为它在http-request头中执行了以下内容类型:
Content-Type: application/json
如果你像我一样使用php,甚至使用Symfony2,你可以简单地扩展json标准的服务器兼容性:http://silex.sensiolabs.org/doc/cookbook/json_request_body.html
Symfony2方式(例如在你的DefaultController中):
$request = $this->getRequest();
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
var_dump($request->request->all());
好处是,你不需要使用jQuery参数,你可以使用AngularJS的原生方式来做这样的请求。
你可以全局定义行为:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
所以你不必每次都重新定义它:
$http.post("/handle/post", {
foo: "FOO",
bar: "BAR"
}).success(function (data, status, headers, config) {
// TODO
}).error(function (data, status, headers, config) {
// TODO
});
如果你不想在解决方案中使用jQuery,你可以试试这个。解决方案从这里获取https://stackoverflow.com/a/1714899/1784301
$http({
method: 'POST',
url: url,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: xsrf
}).success(function () {});