有没有办法检查用户是否已在其他计算机上拥有有效会话?
我想要做的是当用户登录时,销毁他们可能已经拥有的其他会话,这样如果他们忘记从计算机注销说在校园或工作中,然后他们在家登录,它会破坏其他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);
是否会销毁该用户的所有会话,或仅销毁当前会话。
谢谢!
答案 0 :(得分:5)
您可以在用户模型中保存session_id,以便:
当触发注销事件(auth.logout)时,您将清除它。
当触发新的日志记录事件时,您可以检查用户模型中的属性session_id是否为空。
如果不是 - 通过以下方式销毁以前的会话:
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 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);
如果您想在本地进行测试,那么如果您在普通窗口和隐身窗口中打开网站,则似乎可以正常工作。当您登录其中一个时,您将注销另一方-尽管您必须刷新才能看到任何更改。