Laravel - 在登录时销毁现有会话

时间:2014-08-29 18:25:16

标签: php session authentication laravel

有没有办法检查用户是否已在其他计算机上拥有有效会话?

我想要做的是当用户登录时,销毁他们可能已经拥有的其他会话,这样如果他们忘记从计算机注销说在校园或工作中,然后他们在家登录,它会破坏其他2个会话,以便他们不再登录?

Facebook以某种方式使用它。

到目前为止,我唯一的想法就是这样:

$user = User::find(1); // find the user
Auth::login($user); // log them in 
Auth::logout(); // log them out hoping that it will destroy all their sessions on all machines
Auth::login($user); // log them in again so they have a valid session on this machine

我没有机会对此进行测试,我不知道Auth::login($user);是否会销毁该用户的所有会话,或仅销毁当前会话。

谢谢!

4 个答案:

答案 0 :(得分:5)

您可以在用户模型中保存session_id,以便:

  1. 当触发注销事件(auth.logout)时,您将清除它。

  2. 当触发新的日志记录事件时,您可以检查用户模型中的属性session_id是否为空。

  3. 如果不是 - 通过以下方式销毁以前的会话:

  4. Session :: getHandler() - > destroy($ user-> session_id);

    $ user-> session_id = Session :: getId();

    希望这会有所帮助!

答案 1 :(得分:2)

我希望你能看到这份工作:

Session::regenerate(true);

获得新的session_id。

答案 2 :(得分:0)

这可能不是最好的答案,但我首先想到的是降低会话的超时时间。

在app-> config-> session.php中,有一个life和expire_on_close(浏览器)的设置。

我现在尝试调查一下,看看别人是否想出更好的东西。

答案 3 :(得分:0)

我意识到这是一个古老的问题,但是laravel 5.6中现在有一种方法可以完全做到这一点,因此对于以后再来讨论此问题的人可能很有用。您也可以很容易地将此​​方法改装为laravel的早期版本。

请参阅https://laravel.com/docs/5.6/authentication#invalidating-sessions-on-other-devices

中的文档

我和您有相同的用例(登录时注销所有其他设备)。我覆盖了默认的登录方法以添加自己的自定义逻辑(首先从vendor / laravel / framework / src / illuminate / Foundation / Auth / AuthenticatesUsers.php复制默认的登录方法)

在该方法中,有一行if ($this->attemptLogin($request))-在该行中,在return语句之前,将您的调用添加到logoutOtherDevices,如下所示

if ($this->attemptLogin($request)) {

        //log out all other sessions
        Auth::logoutOtherDevices($request->password); //add this line

        return $this->sendLoginResponse($request);
}

还要确保您已根据文档取消注释app / Http / Kernel.php中的Illuminate\Session\Middleware\AuthenticateSession中间件

(请注意,由于我使用的是不具有此方法的较旧版本的laravel,因此我尚未测试上述代码,请参见下文)。不过,这应该在5.6中有效。

Laravel的旧版本

我实际上是在使用laravel 5.5,因此无法使用此便捷方法。幸运的是,它很容易添加。 我打开了一个laravel 5.6项目,并从vendor / laravel / framework / src / illuminate / Auth / SessionGuard.php复制了logoutOtherDevices方法-供参考,我已在下面粘贴

/**
 * Invalidate other sessions for the current user.
 *
 * The application must be using the AuthenticateSession middleware.
 *
 * @param  string  $password
 * @param  string  $attribute
 * @return null|bool
 */
public function logoutOtherDevices($password, $attribute = 'password')
{
    if (! $this->user()) {
        return;
    }

    return tap($this->user()->forceFill([
        $attribute => Hash::make($password),
    ]))->save();
}

然后我将其复制到我的LoginController中-它可以放在您选择的其他位置,但是为了方便/懒惰,将其放在此处。我必须对其进行一些修改,如下所示($this->user()变成了Auth::user()

 /**
 * Invalidate other sessions for the current user.
 * Method from laravel 5.6 copied to here
 *
 * The application must be using the AuthenticateSession middleware.
 *
 * @param  string  $password
 * @param  string  $attribute
 * @return null|bool
 */
public function logoutOtherDevices($password, $attribute = 'password')
{
    if (! Auth::user()) {
        return;
    }

    return tap(Auth::user()->forceFill([
        $attribute => Hash::make($password),
    ]))->save();
}

然后我可以在我的答案前面指定的登录方法中调用此方法,并稍作调整-$this->logoutOtherDevices($request->password);

如果您想在本地进行测试,那么如果您在普通窗口和隐身窗口中打开网站,则似乎可以正常工作。当您登录其中一个时,您将注销另一方-尽管您必须刷新才能看到任何更改。