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

Jus*_*tin 10 php authentication session laravel-5

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

这是发生了什么:

  1. 我以用户A身份登录
  2. 我导航到一个在Session中存储变量X的页面
  3. 我退出了,但没有关闭浏览器.
  4. 会话文件storage/framework/sessions仍在那里,浏览器cookie还活着.
  5. 我以用户B身份登录
  6. 旧会话文件 storage/framework/sessions已删除,并且存在新的会话文件.
  7. 我查看了新的会话文件 - 惊喜!变量X在注销时幸存并且仍在那里,用户B可以访问!

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

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

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

这意味着我作为程序员负责在新的(或相同的)用户登录时完全清除当前会话中的所有敏感数据.

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

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

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

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

我对此感到困惑:

我今天又做了另一件事并意识到问题所在:Session :: flush()不会删除应用创建的会话数据,例如购物车详细信息

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

当身份验证过期或用户注销时,如何告诉Laravel我希望将旧会话数据与用户身份验证数据一起删除?

Mar*_*nJH 5

laravel文档中,它说你可以:

从会话中删除项目

Session::forget('key');
Run Code Online (Sandbox Code Playgroud)

从会话中删除所有项目

Session::flush();
Run Code Online (Sandbox Code Playgroud)

您可以导航到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 : '/');
    }
Run Code Online (Sandbox Code Playgroud)

   /**
     * 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 : '/');
    }
Run Code Online (Sandbox Code Playgroud)

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

更新

根据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
Run Code Online (Sandbox Code Playgroud)