繁体   English   中英

Laravel会话随机到期

[英]Laravel session expires randomly

我们在我们的网站上遇到过这个问题,我们从用户那里得到了CSRF错误。 会话cookie和会话数据设置为在12小时内过期,会话驱动程序设置为使用Redis。 在我们的调查之后,我们最终成功地模拟了异常情况,所以这里是场景:

用户在网站上打开两个不同的页面,使用Chrome浏览器打开“打开上次关闭的标签”设置。 其中一个页面上有一个表单(例如登录),然后用户在某个时刻退出浏览器。 他第二天重新打开浏览器(12小时过去,因此会话cookie和会话数据已过期)Chrome尝试重新加载所有打开的页面。 它向服务器发送两个同时发出的请求,而它们都没有会话cookie。 在服务器端,Laravel为每个会话ID生成两个不同的会话ID。 Chrome接收它们并覆盖其他会话cookie上的一个。 一旦用户尝试提交表单(例如登录),它就会在表单会话cookie被覆盖时生成CSRF错误。

我们还有一些AJAX帖子请求,由于这种情况我们失败了CSRF错误。

我想知道Laravel是否能够以安全的方式为两个请求生成相同的会话ID。

有没有人有任何想法我们如何解决这个问题?

PS:我们正在使用laravel 4.1和这个会话配置:

return array(

    'driver' => 'redis',

    'lifetime' => 720,

    'expire_on_close' => false,

    'files' => storage_path().'/sessions',

    'connection' => null,

    'table' => 'sessions',

    'lottery' => array(2, 100),

    'cookie' => 'laravel_session',

    'path' => '/',

    'domain' => '.ourdomain.com',
);

经过我们公司对这个问题的大量调查,我得出了这个结果,我希望它有所帮助,首先这里是我们的环境规范:

  • PHP:5.3.3
  • LARAVEL:4.1
  • 操作系统:服务器上的centos 6和开发环境中的os x mavericks
  • APACHE:2
  • MYSQL:5.6.19
  • REDIS:2.4.10
  • PREDIS:0.8。*

首先,似乎TokenMistmatch异常发生在各种不同的条件下,我几乎调查了所有这些异常,并且能够解决其中的一些,一些取决于会话背后的逻辑,一些可能是错误。 在下文中,我将解释我面临的每种情况。

1.过期会议

假设您已经将会话配置为3个小时,用户打开表单并出于某种原因离开计算机(获得一杯咖啡),因此在会话过期3小时后,他尝试提交表单并获取令牌例外。 这就是为什么每个人一旦进入同时获得令牌错误,无论应用程序有多稳定,我可以设想两种方法来防止它,并且他们使用ajax及时更新会话cookie,或者增加会话过期时间相当长的时间。

2.会话过期时的并发请求

有时在第一页的加载时发生并发请求,例如用户在chrome上打开了两个不同的选项卡,当他重新打开时,chrome chrome会同时发送请求,或者您可能在第一页的加载时有多个并发的ajax请求应用。 所以请注意,会话cookie是在收到第一个响应后收到的,但您可以在此之前发送下一个请求,因此您将在每个请求上获得一个新会话(新cookie),这可能会导致令牌异常,如果其中一个请求填充表单。 您可以根据它的源来阻止这种情况,例如,如果ajax请求导致问题并且您没有在ajax响应中使用会话,则可以在第二种情况下禁用发送会话cookie(如果请求是ajax)(单击多次提交按钮)一旦提交,您可以简单地禁用该按钮。

3.登录时的并发请求

当登录发生时,出于安全原因,laravel会更改会话ID,复制会话数据和DESTROYS THE LAST SESSION,因此在登录并发请求时会出于某种原因说(多次单击登录按钮),以便重新生成会话ID多次和DESTROYS在服务器端最后生成的会话,因为其中一些请求仍然使用先前的会话ID(在服务器端不再存在)它导致重新生成CSRF令牌,请注意通常laravel不如果可以在guest虚拟机(未登录)会话中找到令牌,则在登录时重新生成令牌,但在这种情况下,因为guest虚拟机会话被销毁,因此它将重新生成令牌,并且可能导致其他请求中的令牌异常。使用原始令牌。 另请注意,此问题不仅会导致令牌异常,还会导致用户在一次请求后被注销,因为并发请求可以更改登录的会话。 我在lauminvel代码中更改了一行,在Illuminate\\Auth\\Guard:updateSession解决了这个问题:

 protected function updateSession($id)
 {
        $this->session->put($this->getName(), $id);

        //$this->session->migrate(true);
        $this->session->migrate()
 }

将true传递给会话存储的migrate方法将导致在迁移后销毁服务器上的会话,因此现在数据将保留在服务器上并在其到期时间而不是在此请求上销毁,它将解决问题。 我不知道我们是否可以将其称为laravel中的错误,但我想我们可以为此提出更好的解决方案。

4.浏览器

调查日志后发现,其中一些令牌异常是因为用户的浏览器不接受会话cookie,我在iOS Safari上看到的最多,我相信这是我们无能为力的事情。

5. Redis bug

我们服务器上的一些令牌例外是因为redis,因为某些原因,laravel在打开会话时无法从redis服务器读取会话数据,因此会导致CSRF令牌的重新生成。 它是在我们的服务器上随机发生的,所以我尝试更改会话驱动程序,这种类型的异常逐渐消失。 我尝试过数据库,apc和文件驱动程序,没有人产生这个问题。 我还没有找到导致错误的原因,但我认为它可能是redis或predis库的错误。 (如您所知,由于兼容性问题,laravel 4.1未使用最新版本的predis)。

好的,这是我过去两个月在这个问题上的经历。 我希望它可能改变你对这个问题的解决方案的观点,最重要的是令牌异常不会发生,因为一个原因可能是多个问题的结果。 如果您遇到类似事件或者您有新事物,请与我分享。

我已经多次遇到过这个问题,没有具体原因,Amir也没有提到过。

清除域cookie适用于我看到的场景。

在我的情况下,这是缓存配置文件的问题。 Laravel创建一个缓存在bootstrap / cache文件夹中的配置文件。 将此config.php文件重命名为其他内容并运行“php artisan cache:clear”

然后运行该网站,它应该工作正常

这可能与这个众所周知的问题有关

Laravel 5.0 - Asyncronous AJAX请求导致会话变量被覆盖#7549

如果多个请求尝试覆盖会话并且会话文件没有锁定,则可能导致会话文件损坏(覆盖)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM