首页 文章

Laravel - 会话数据可以在注销/登录后继续存在,即使对于不同的用户也是如此

提问于
浏览
10

今天我在检查由Laravel 5创建的 storage/framework/sessions 文件夹中的会话文件时发现了一些令人不安的事情 .

这是发生了什么:

  • 我以用户A身份登录

  • 我导航到一个在Session中存储变量X的页面

  • 我退出了,但没有关闭浏览器 .

  • storage/framework/sessions 中的会话文件仍然存在,浏览器cookie仍然存在 .

  • 我以用户B身份登录

  • storage/framework/sessions 中的旧会话文件被删除,并且存在新的会话文件 .

  • 我查看了新的会话文件 - 惊喜!变量X在注销时幸存并且仍在那里,用户B可以访问!

它导致安全问题,因为现在用户B可以访问用户A的数据 .

在通过Laravel源代码进行调试时,我发现在注销/登录过程中永远不会清除会话存储 . 在 Illuminate\Auth\Guard::clearUserDataFromStorage() 方法中只删除了登录凭据,但是所有会话Store属性仍然存在,然后调用 $kernel->terminate($request, $response); 时,这又导致 Illuminate\Session\Middleware\StartSession::terminate() 调用 Store::save() ,盲目地将 $this->attributes 保存到新会话中,忽略了这样的事实:它现在属于另一个用户 .

从一方面看,这似乎是合乎逻辑的--Laravel对我的数据没有任何假设,我是否希望它与认证一起过期 . 但是,如果将某些敏感数据附加到身份验证对象并与之一起过期,则将其记录在某处可能会很棒 .

This means that I as a programmer am responsible for completely clearing away all the sensitive data from current session when a new (or the same) user is logging in.

注销时清除将不可靠,因为用户可能永远不会单击“注销”链接,而是等待会话“过期”,这对于Laravel仍然无法清除会话 .

还有一点要记住:我不应该过早清除会话 - 必须存在AntiForgery令牌,否则登录表单将始终失败 .

我找到了一个论坛主题,也试图解决一些类似的问题:

http://laravel.io/forum/04-27-2014-how-to-expire-session-data

我对此感到困惑:

今天我再次讨论它并意识到问题所在:Session :: flush()不会删除应用程序创建的会话数据,例如购物车详细信息

如果这是真的,那么完全摆脱会话的唯一方法就是使用PHP本机 session_unset()session_destroy() 但我不想那样 - 我宁愿找一个更干净的Laravel-ish解决方案,如果可能的话 .

How do I tell Laravel that I want my old session data to be removed together with user authentication data when authentication expires or user logs out?

1 回答

  • 4

    laravel docs它说你可以:

    Removing An Item From The Session

    Session::forget('key');
    

    Removing All Items From The Session

    Session::flush();
    

    您可以导航到AuthenticatesAndRegistersUsers.php特征并重写

    /**
         * Log the user out of the application.
         *
         * @return \Illuminate\Http\Response
         */
        public function getLogout()
        {
            $this->auth->logout();
    
            return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
        }
    

    /**
         * Log the user out of the application.
         *
         * @return \Illuminate\Http\Response
         */
        public function getLogout()
        {
            Session::flush();
    
            $this->auth->logout();
    
            return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
        }
    

    我不知道这是否真的有效,但试一试:)

    Update

    According to this answer here on Stack Overflow,您可以将会话设置为在浏览器关闭或XXX分钟后过期 . 与上述解决方案一起使用,应该解决问题吗?

    在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' => 120,
    
        'expire_on_close' => false
    

相关问题