我正在使用Laravel(后端)和ReactJS与JQuery(前端)构建类似CMS的Web应用程序。
我决定将现有的Web API放入一个单独的域(api.test.com),我的用户界面位于不同的域(test.com)。
在 test.com 上,我向 api.test.com 发起了ajax请求,以修改服务器上的某些资源:
$.ajax({
url: "api.test.com",
method: 'POST',
data: {...}
success: function (no) {
// ...
}
});
当然,由于安全问题,它是非法的。但是,我可以配置我的Web服务器:
对于Nginx:
add_header Access-Control-Allow-Origin http://test.com;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE;
add_header Access-Control-Allow-Headers X-Requested-With,X-CSRF-TOKEN,X-XSRF-TOKEN;
Access-Control-Allow-Origin 问题已得到完美解决,但由于 Laravel的CSRF 保护而出现了另一个问题......
Laravel默认需要包含在请求中的CSRF令牌(POST,PUT ......将修改资源)。
就我而言,我必须在 api.test.com 而不是 test.com 上生成 csrf_token ,因为不同的域名不会共享令牌。
我按照Laravel的用户指南将这些代码添加到我的前端:
$.ajax({
url: "api.test.com/token", // simply return csrf_token();
method: "GET",
success: function (token) {
// Now I get the token
_token = token;
}.bind(this)
});
并修改先前的请求实现:
$.ajax({
url: "api.test.com",
method: 'POST',
headers: {
"X-CSRF-TOKEN": _token // Here I passed the token
},
data: {...}
success: function (no) {
// ...
}
});
但是Laravel回复了状态代码500.然后我检查了 VerifyCsrfToken.php :
protected function tokensMatch($request)
{
$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
if (!$token && $header = $request->header('X-XSRF-TOKEN')) {
$token = $this->encrypter->decrypt($header);
}
// Log::info($request->session()->token() . " == $token");
return Str::equals($request->session()->token(), $token);
}
$ token ,我 POST '与...不同( $ request-> session() - > token())。
我发现调用$ .ajax时,服务器上的验证令牌是不同的。
我尝试将两个请求放在同一个会话中(通过更改cookie),但这是不可能的。
我花了很多时间来解决这个问题,但没有解决这个问题。
有任何想法或解决方案吗?
谢谢, Micooz
答案 0 :(得分:3)
感谢您回答我的问题。我已经考虑禁用对某些URI的CSRF保护,但我不想承担这些风险。
我的问题的关键点是$ .ajax在请求之前忘记携带cookie,结果令牌验证失败。
现在我设置了JQuery Ajax,让它在发出请求之前携带cookie。
$.ajaxSetup({
xhrFields: { withCredentials: true }
});
和Nginx conf:
add_header Access-Control-Allow-Credentials true;
顺便说一句,没有必要在数据中包含令牌:{}(表单)。
所有问题都已解决,对我来说非常有效。
答案 1 :(得分:0)
Laravel希望令牌作为数据变量(包含在您的字段中),var的名称需要_token
尝试更改它。
另一种解决方案是将数据中的令牌包含在标题中。
$.ajax({
url: "api.test.com",
method: 'POST',
data: { _token : _token }
success: function (no) {
// ...
}
});
答案 2 :(得分:-1)
您可以关注此网址
http://laravel.io/forum/11-14-2014-disabling-the-csrf-middleware-in-laravel-5
在此链接中,您需要将VerifyCsrfToken
类包含在新的一个类中,您可以在其中指定不使用csrf_token的操作