Laravel如何具体构建和检查CSRF令牌?

时间:2014-03-24 13:46:47

标签: php laravel laravel-4 token csrf

我在公共网站上使用Laravel的CSRF保护。然而,由于Laravel使用会话来维护这一点,我担心用户可能会离开他们的计算机并返回他们之前打开的页面,但却发现ajax请求不起作用。 ajax请求不起作用,因为会话超时(并且令牌不再有效?)。如果这些用户已登录"用户,然后我可以简单地将它们重定向回登录页面。由于他们是公共用户,因此用户被迫刷新页面以使其恢复工作(笨拙)。

或者我错了吗?是否仍然会通过Laravel对CSRF令牌进行验证(即使会话超时后,页面仍将通过令牌发送......但是Laravel会用它做什么?)。最佳解决方案是使令牌部分基于时间戳,以便我们可以将令牌到期限制与会话时间限制区分开来。我可以让我的CSRF代币持续2天(因此只有那些离开2天的用户才能返回死页)。

最终这让我想到了一个问题: Laravel框架中的具体代码在哪里处理这个问题?我目前正试图找到它。另外,我可以轻松替换掉,或者我还是创建自己的csrf_token();版本输出到我的页面然后我需要创建自己的路由过滤器来配合它。 / p>

2 个答案:

答案 0 :(得分:25)

Laravel通过将令牌保存在会话中来为您提供便利,但代码实际上是您的(根据需要进行更改)。看一下你应该看到的filters.php

Route::filter('csrf', function()
{
    if (Session::token() != Input::get('_token'))
    {
        throw new Illuminate\Session\TokenMismatchException;
    }
});

它告诉我们如果你有路线:

Route::post('myform', ['before' => 'csrf', 'uses' => 'MyController@update']);

用户会话过期,它会引发异常,但您可以自己完成工作,将您自己的令牌存储在您认为更好的地方,而不是抛出该异常,将您的用户重定向到登录页面:< / p>

Route::filter('csrf', function()
{
    if (MySession::token() != MyCSRFToken::get())
    {
        return Redirect::to('login');
    }
});

而且,是的,你可以创建自己的csrf_token(),你只需要在Laravel之前加载它。如果你看一下Laravel源代码中的helpers.php文件,你会看到它只创建了那个函数,如果它还没有存在:

if ( ! function_exists('csrf_token'))
{
    function csrf_token()
    {
       ...
    }
}

答案 1 :(得分:4)

由于这已经成为一个受欢迎的问题,我决定发布我的工作非常好的特定解决方案......

您很可能会在所有网页的顶部使用header.php或部分局部视图,请确保其位于<head>部分:

<meta name="_token" content="<?=csrf_token(); ?>" />  

在你的filters.php中:

Route::filter('csrf', function() 
{
   if (Request::ajax()) {
        if(Session::token() != Request::header('X-CSRF-Token')){
            throw new Illuminate\Session\TokenMismatchException;
        } 
    }
});

在你的routes.php中

Route::group(array('before' => 'csrf'), function(){

    // All routes go in here, public and private

});