会话超时后出现laravel-csrf令牌不匹配异常


laravel csrf token mismatch exception after session timeout

在我们的laravel 5应用程序中,登录是通过ajax进行的。如果用户在会话到期之前注销并重新登录,则一切正常。但是,如果用户注销并在该页面上保持空闲直到会话过期,则如果用户尝试重新登录,则会得到csrfTokenMismatch异常。

我知道在verifyCsrfToken中间件中,laravel会检查会话是否与csrf令牌匹配。同样在Guard.php logout()方法中,会话将在注销时被清除。

所以我的问题是:

注销时会话真的被刷新了吗?如果是的话,为什么用户仍然可以在我设置的会话到期之前重新登录?

会话过期时csrf令牌会发生什么?

最后,这个问题通常是如何以优雅的方式处理的?

提前感谢!

这个答案参考了5.4版本,可能是以前的版本,但我还没有测试过。

问题的根源是客户端的CSRF令牌已过期,这会导致使用该令牌对服务器进行POST失败。

如果你使用AJAX,你可以使用API路由,默认情况下不做CSRF验证。

您可以关闭特定URI的CSRF验证。在这种情况下,我将关闭/logout的CSRF验证。如果确实希望从验证中排除某些URI,则此方法效果良好。

app/Http/Middleware/VerifyCsrfToken.php/***应排除在CSRF验证之外的URI。**@var数组*/受保护$except=['/注销'];

此外,当CSRF错误发生时,您应该以适合您的应用程序的方式处理它。下面是一个你可以做的非常基本的事情的例子

app/Exceptions/Handler.php/***将异常呈现为HTTP响应。**@param''Illuminate''Http''Request$Request*@param''Exception$Exception*@return ''Illuminate''Http''Response*/公共函数呈现($request,Exception$Exception({if($exception instanceof''Illuminate''Session''TokenMismatchException({//令牌不匹配是一个安全问题,请确保注销。Auth::logout((;//告诉用户发生了什么。session((->flash('警告','您的会话已过期。请登录以继续。'(;//转到登录。return redirect((->route('登录'(;}return parent::render($request,$exception(;}

顺便说一句,要测试这两项更改,您可以修改会话设置。我只是将生存期设置为1进行测试。然后,在完成时将其设置为后退(默认情况下为120(。您需要登录,加载表单页面,等待一分钟以上,然后尝试POST。

config/session.php/*|--------------------------------------------------------------------------|会话生存期|--------------------------------------------------------------------------||您可以在此处指定您希望会话的分钟数|以允许在其到期之前保持空闲。如果你想要它们|要在浏览器关闭时立即过期,请设置该选项。|*/"寿命"=>1,

有一个名为XSRF Token的cookie,默认生存时间为2小时。。。

我通过修改App/Exceptions/Handler.php:来处理登录表单上的TokenMissmatchExceptions

// ....
use Illuminate'Session'TokenMismatchException;
// ....

public function render($request, Exception $e)
{
    if($e instanceof TokenMismatchException) {
        $uri = 'Route::current()->uri();
        if($uri == "login") {
            return redirect()->route('your.login.route')
                             ->withErrors("Login Form was open too long. 
                                           Please try to login again");
        }
    }
    return parent::render($request, $e);
}

在您的情况下,我认为使用会真正受益

https://github.com/GeneaLabs/laravel-caffeine

我个人处理这样的非ajax情况,您可以针对ajax请求对其进行调整,以返回一些有用的json来处理错误:

public function render($request, Exception $e)
    {
         if ($e instanceof 'Illuminate'Session'TokenMismatchException) {
              return redirect()
                  ->back()
                  ->withInput($request->except('_token'))
                  ->withMessage('Your explanation message depending on how much you want to dumb it down, lol! ');
        }
        return parent::render($request, $e);
    }
}