Mic*_*ooz 5 php ajax jquery csrf laravel
我正在使用 Laravel(后端)和带有 JQuery(前端)的 ReactJS 构建一个类似 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) {
// ...
}
});
Run Code Online (Sandbox Code Playgroud)
当然,由于安全问题,这是非法的。但是,我可以配置我的网络服务器:
对于 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;
Run Code Online (Sandbox Code Playgroud)
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)
});
Run Code Online (Sandbox Code Playgroud)
并修改之前的请求实现:
$.ajax({
url: "api.test.com",
method: 'POST',
headers: {
"X-CSRF-TOKEN": _token // Here I passed the token
},
data: {...}
success: function (no) {
// ...
}
});
Run Code Online (Sandbox Code Playgroud)
但 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);
}
Run Code Online (Sandbox Code Playgroud)
我“ POST ”到的$token与它原来的不同($request->session()->token())。
我发现调用 $.ajax 时服务器上的验证令牌不同。
我尝试将两个请求放在同一个会话中(通过更改 cookie),但这是不可能的。
我花了很多时间来解决这个问题但没有解决。
有什么想法或解决方案吗?
谢谢,米库兹
谢谢你回答我的问题。我考虑过禁用某些 URI 的 CSRF 保护,但我不想冒这些风险。
我的问题的关键点是 $.ajax 忘记在请求之前携带 cookie,导致令牌验证失败。
现在我设置了JQuery Ajax,让它在发出请求之前携带cookie。
$.ajaxSetup({
xhrFields: { withCredentials: true }
});
Run Code Online (Sandbox Code Playgroud)
和 Nginx 配置:
add_header Access-Control-Allow-Credentials true;
Run Code Online (Sandbox Code Playgroud)
顺便说一句,没有必要在数据中包含令牌:{}(表单)。
所有问题都已解决,并且对我来说非常有效。
| 归档时间: |
|
| 查看次数: |
3954 次 |
| 最近记录: |