我在公共网站上使用Laravel的CSRF保护。然而,由于Laravel使用会话来维护这一点,我担心用户可能会离开他们的计算机并返回他们之前打开的页面,但却发现ajax请求不起作用。 ajax请求不起作用,因为会话超时(并且令牌不再有效?)。如果这些用户已登录"用户,然后我可以简单地将它们重定向回登录页面。由于他们是公共用户,因此用户被迫刷新页面以使其恢复工作(笨拙)。
或者我错了吗?是否仍然会通过Laravel对CSRF令牌进行验证(即使会话超时后,页面仍将通过令牌发送......但是Laravel会用它做什么?)。最佳解决方案是使令牌部分基于时间戳,以便我们可以将令牌到期限制与会话时间限制区分开来。我可以让我的CSRF代币持续2天(因此只有那些离开2天的用户才能返回死页)。
最终这让我想到了一个问题: Laravel框架中的具体代码在哪里处理这个问题?我目前正试图找到它。另外,我可以轻松替换掉,或者我还是创建自己的csrf_token();
版本输出到我的页面然后我需要创建自己的路由过滤器来配合它。 / p>
答案 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
});