JQueryAJAX跨站请求在LaravelCSRF保护下
JQuery AJAX cross-site request under Laravel CSRF protection
我正在使用 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) {
// ...
}
});
当然,由于安全问题,这是非法的。但是,我可以配置我的网络服务器:
对于 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 而不是 上生成 csrf_token test.com 因为不同域不共享令牌。
我遵循 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);
}
我'POST'的$token与原来的不同( $request->session()->token()).
我发现调用 $.ajax.
时服务器上的验证令牌不同
我尝试将两个请求放在同一个会话中(通过更改 cookie),但这是不可能的。
我花了很多时间来解决这个问题,但没有解决。
有什么想法或解决方案吗?
谢谢,
米库兹
Laravel 期望令牌作为数据变量,包含在您的字段中,变量的名称需要是 _token
尝试更改它。
另一种解决方案是将令牌包含在您的数据中,而不是 headers。
$.ajax({
url: "api.test.com",
method: 'POST',
data: { _token : _token }
success: function (no) {
// ...
}
});
你可以关注这个url
http://laravel.io/forum/11-14-2014-disabling-the-csrf-middleware-in-laravel-5
在此 link 中,您需要用新的 class 结束 VerifyCsrfToken
class,在其中指定您不想使用的操作 csrf_token
感谢您回答我的问题。我考虑过禁用 对某些 URI 的 CSRF 保护,但我不想冒这些风险。
我的问题的重点是$.ajax在请求前忘记携带cookies,导致token验证失败。
现在我设置 JQuery Ajax,让它在发出请求之前携带 cookie。
$.ajaxSetup({
xhrFields: { withCredentials: true }
});
和 Nginx 配置:
add_header Access-Control-Allow-Credentials true;
顺便说一句,没有必要在数据中包含令牌:{}(Form).
所有问题都解决了,非常适合我。
我正在使用 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) {
// ...
}
});
当然,由于安全问题,这是非法的。但是,我可以配置我的网络服务器:
对于 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 而不是 上生成 csrf_token test.com 因为不同域不共享令牌。
我遵循 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);
}
我'POST'的$token与原来的不同( $request->session()->token()).
我发现调用 $.ajax.
时服务器上的验证令牌不同我尝试将两个请求放在同一个会话中(通过更改 cookie),但这是不可能的。
我花了很多时间来解决这个问题,但没有解决。
有什么想法或解决方案吗?
谢谢, 米库兹
Laravel 期望令牌作为数据变量,包含在您的字段中,变量的名称需要是 _token
尝试更改它。
另一种解决方案是将令牌包含在您的数据中,而不是 headers。
$.ajax({
url: "api.test.com",
method: 'POST',
data: { _token : _token }
success: function (no) {
// ...
}
});
你可以关注这个url
http://laravel.io/forum/11-14-2014-disabling-the-csrf-middleware-in-laravel-5
在此 link 中,您需要用新的 class 结束 VerifyCsrfToken
class,在其中指定您不想使用的操作 csrf_token
感谢您回答我的问题。我考虑过禁用 对某些 URI 的 CSRF 保护,但我不想冒这些风险。
我的问题的重点是$.ajax在请求前忘记携带cookies,导致token验证失败。
现在我设置 JQuery Ajax,让它在发出请求之前携带 cookie。
$.ajaxSetup({
xhrFields: { withCredentials: true }
});
和 Nginx 配置:
add_header Access-Control-Allow-Credentials true;
顺便说一句,没有必要在数据中包含令牌:{}(Form).
所有问题都解决了,非常适合我。