Laravel在Ajax登录后返回CSRF令牌不匹配(响应代码419)



问题:当我通过Ajax调用登录用户时,Laravel在同一页面上的下一个Ajax Post上返回419 CSRF令牌不匹配。

在结账页面上,我有一个用于现有用户的登录按钮。单击时,它会向用户显示登录模式。如果凭据匹配,则用户将在不刷新页面的情况下登录。当用户没有帐户时,会显示一个注册模式,注册用户并登录。

当用户完成结账过程并提交表单时,Laravel返回一个CSRF令牌不匹配错误。

成功登录后,Laravel会使用AuthenticatesUsers特性发送登录响应。

然后,登录响应调用session((上的rebuild方法,该方法将生成一个新的CSRF令牌。因此,用于登录用户的csrf令牌对于下一个POST请求不再有效。

/**
* Send the response after the user was authenticated.
*
* @param  IlluminateHttpRequest  $request
* @return IlluminateHttpResponse
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
if ($response = $this->authenticated($request, $this->guard()->user())) {
return $response;
}
return $request->wantsJson()
? new Response('', 204)
: redirect()->intended($this->redirectPath());
}

我通过在成功登录响应中返回新的csrf令牌来处理这一问题,并将其存储起来,以便在下一次POST请求中使用。我所说的存储是指将其作为变量保存在JavaScript中,或者在我的情况下使用应用程序状态中设置的React.js。

在Auth/LognController中,我添加了经过身份验证的方法,它覆盖了AuthenticatesUsers特性中的相同方法。

然后,在验证请求的行之后,我检查这是否是Ajax请求,并返回新的CSRF令牌。

protected function authenticated(Request $request, $user) {
$credentials = array (
'email'    => $request->get('email'),
'password' => $request->get('password'),
);
$valid = Auth::validate($credentials);

if ($valid && $request->ajax()) {
return response()->json([
'auth'     => auth()->check(),
'user'     => $user,
'intended' => $this->redirectPath(),
'csrf'     => csrf_token(),
]);
}
// Nothing changed from here on
}

最新更新