获取CSRF令牌不匹配- Vue axios对Laravel Api路由



我试图在服务器端的会话中保存客户购物车。客户不需要登录。所以没有Laravel Sanctum或Passport等。Laravel和Vue运行在不同的服务器上(后端:localhost:8000和前端:localhost:9000)。

这里是我的api.php路线。
Route::get('get-token', function (Request $request) {
return [
'_token' => $request->session()->token()
];    
})->middleware('web');
Route::group(['prefix'=>'v1'], function() {
Route::resource('cart', AppHttpControllersApiV1CartController::class)->middleware('web');
Route::resource('products', AppHttpControllersApiV1ProductController::class);
}

GET/cart请求通过axios和insomnia都可以正常工作:

这里是corospond CartController函数索引:

function index() {
return request()->session()->get('cart');
}

现在的问题是

但是通过axios的POST请求被拒绝,因为419 CSRF令牌不匹配。

奇怪的是,我可以通过失眠发出POST请求。首先从服务器请求令牌,然后在POST请求的主体中指定_token。

> POST /api/v1/cart HTTP/1.1
> Host: localhost:8000
> User-Agent: insomnia/2021.5.3
> Cookie: laravel_session=ZzbpJsfvV22NjO3TB5C3ekiCIp7hlPAcaaZHTkfU; XSRF-TOKEN=eyJpdiI6IjhvVFpWMWtwMm0vU1RKNHB2VzdMdUE9PSIsInZhbHVlIjoiaDNEWTlhcTBRTWI0aXhkaU54Z3I5VndoWFg4Q1A1WmpJUDI1S2hFRGtiMUUwYUl0OEN6S0Q3RVFDZDJXSTNvdTllUXMzN0o1RU94blpqVTdpdTcxaTVvZjlwdFk2Z3djeldteHp0R3Q4UEVjMEovbGk2SHJnVXZmbzRBUzI1RHkiLCJtYWMiOiI2MDMyYzFjNWVjODY4NjRjMTk4NGNmMmI3Yjg4M2VjYzU5YzcwZGRkNDIxMTRiOTc1N2FkMmQ2NTc4YTA5MjhiIiwidGFnIjoiIn0%3D
> Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
> Accept: application/json
> Content-Length: 293
| --X-INSOMNIA-BOUNDARY
| Content-Disposition: form-data; name="product_id"
| 1
| --X-INSOMNIA-BOUNDARY
| Content-Disposition: form-data; name="amount"
| 1
| --X-INSOMNIA-BOUNDARY
| Content-Disposition: form-data; name="_token"
| YgKRkQc9D5GWOPiP8zqVEcoA4FuvESf02SSjy7U3
| --X-INSOMNIA-BOUNDARY--

我完全不明白为什么我在api路由中使用web中间件。api中间件将为我生成以下500条错误消息:

"message": "Session store not set on request.",

这是我的axios请求:

axios.get('http://localhost:8000/api/get-token').then(response => {
const _token = response.data._token
const bodyFormData = new FormData()
bodyFormData.append('product_id', product.id)
bodyFormData.append('_token', _token)
const headers = {
'Content-Type': 'multipart/form-data',
'Access-Control-Allow-Credentials': true,
'_token': _token             
}
axios({
method: "post",
url: 'cart',
data: bodyFormData,
headers: headers,
}).then((res) => {
console.log('res',res)
}).catch((err) => {console.log(err)})
}); 

这真是一篇很长的文章。我希望我已经提供了所有必要的信息。

  1. 我绝对不明白为什么我在api路由中使用web中间件。
  • 这是因为API路由没有为应用启用会话,因为它期望应用使用令牌,所以为了使用会话,你需要有"Web"中间件

令牌不匹配错误可能是因为通过get-token端点生成/提供的令牌不是正确的

  • 我看到的解决方案是添加/购物车路由作为CSRFTokenMatch的例外路由,打开App/Http/Middleware/VerifyCsrfToken.php文件并在受保护的$except数组中添加路由。这不是一件理想的事情,但这将解决你的问题,并帮助你继续前进。

另一个使你的应用程序安全的选择是使用Laravel Sanctum并为每个来宾用户生成一个令牌(使用来宾模型),如果你需要帮助,我可以解释更多,但这是一个有点不同的场景

我的第一个猜测是你没有发送cookie,需要做

axios.defaults.withCredentials = true

或者,更安全(因为它限制了withCredentials在您真正想要使用它的时候):

const axiosWithCredentials = axios.create({
withCredentials: true
});
axiosWithCredentials.get('http://localhost:8000/api/get-token').then(response => {
const _token = response.data._token
const bodyFormData = new FormData()
bodyFormData.append('product_id', product.id)
bodyFormData.append('_token', _token)
const headers = {
'Content-Type': 'multipart/form-data',
'Access-Control-Allow-Credentials': true,
'_token': _token             
}
axiosWithCredentials({
method: "post",
url: 'cart',
data: bodyFormData,
headers: headers,
}).then((res) => {
console.log('res',res)
}).catch((err) => {console.log(err)})
}); 

相关内容

  • 没有找到相关文章