会话超时后{laravel csrf令牌不匹配异常

时间:2015-07-03 15:57:29

标签: php ajax session laravel

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

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

所以我的问题是:

是会话在注销时真的刷新了,如果是这样,用户如何在我设置的会话到期之前重新登录?

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

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

提前致谢!

3 个答案:

答案 0 :(得分:3)

这个答案是参考5.4版,也许是以前的版本,但我没有测试过。

问题的根源是客户端的CSRF令牌已过期,这使得对服务器的任何POST都失败了。

如果您使用的是AJAX,则可以使用默认情况下不进行CSRF验证的API路由。

可以关闭特定URI的CSRF验证。在这种情况下,我正在关闭/logout的CSRF验证。如果真正希望从验证中排除某些URI,则此方法很有效。

app/Http/Middleware/VerifyCsrfToken.php

/**
 * The URIs that should be excluded from CSRF verification.
 *
 * @var array
 */
protected $except = [
   '/logout'
];

此外,您应该以适合您的应用程序的方式处理CSRF错误。下面是一个非常基本的例子。

app/Exceptions/Handler.php

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)
{
    if($exception instanceof \Illuminate\Session\TokenMismatchException){
        // token mismatch is a security concern, ensure logout.
        Auth::logout();

        // Tell the user what happened.
        session()->flash('alert-warning','Your session expired. Please login to continue.');

        // Go to login.
        return redirect()->route('login');
     }

    return parent::render($request, $exception);
}

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

config/session.php

    /*
    |--------------------------------------------------------------------------
    | Session Lifetime
    |--------------------------------------------------------------------------
    |
    | Here you may specify the number of minutes that you wish the session
    | to be allowed to remain idle before it expires. If you want them
    | to immediately expire on the browser closing, set that option.
    |
    */

    'lifetime' => 1,

答案 1 :(得分: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);
}

答案 2 :(得分:0)

在你的情况下,我认为你真的会受益于这个:

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);
    }
}