namespace App\Http\Controllers\Admin\Auth;
use Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
use AuthenticatesUsers;
public function __construct()
{
$this->middleware('guest:admin', ['except' => 'logout']);
}
protected function guard()
{
return Auth::guard('admin');
}
public function logout()
{
// Get the session key for this user
$sessionKey = $this->guard()->getName();
// Logout current user by guard
$this->guard()->logout();
// Delete single session key (just for this user)
$request->session()->forget($sessionKey);
// After logout, redirect to login screen again
return redirect()->route('admin.login');
}
// ... Other code ...
}
// get current user
$user = Auth::user();
// logout user
$userToLogout = User::find(5);
Auth::setUser($userToLogout);
Auth::logout();
// set again current user
Auth::setUser($user);
5 回答
如果使用Laravel 5.2,则可以将会话存储引擎更改为数据库 . 在这种情况下,每个会话记录也将包含用户的ID .
您只需要从数据库中删除相应的行 .
试图避免额外的复杂性,如向db添加字段,经过一些调查,我遇到了下一个解决方案 .
Idea基于Laravel 5.4,但应与所有5.x版本兼容 .
问题在于Laravel处理注销的方式 . 正如我们在_1742621中看到的那样_
第
$request->session()->invalidate();
行是刷新请求会话数据并重新生成ID . 所以在这之后,如果我们启用了多个防护,他们都将被注销 .我们的想法是只删除一个会话密钥,该密钥对应于我们正在注销的当前用户 . 如果我们检查我们的会话(注意“login_ *”键),当来自不同警卫的用户登录时,我们将得到如下内容:
我们只需要删除这个单独的相应密钥,而不是刷新整个会话 . 要获取当前保护会话名称(上面示例中的会话密钥),我们可以使用guard方法:https://github.com/laravel/framework/blob/5.4/src/Illuminate/Auth/SessionGuard.php#L622
现在我们拥有执行此任务所需的一切 . 以下是我目前正在进行的项目中的示例:
使用
LoginController::logout
方法,我们用我们的自定义覆盖特征注销(默认的Laravel注销逻辑),几乎相同,但这将允许我们注销单个用户 .同样的逻辑适用于我们所有的登录控制器,具体取决于我们拥有多少不同的防护 .
我刚刚完成了这个解决方案,经过快速测试后似乎工作正常,但请在实施前仔细检查 .
我不知道它是否会起作用,但您可以尝试:
我认为最快的解决方案是在用户数据库表中添加一个标志,例如布尔列
to_logout
,并在Auth中间件中添加类似此代码的内容 .查看docs,似乎没有任何内置函数,类似的请求been proposed也描述了跟踪在多个设备上打开多个会话的单个用户的问题 .
我相信您需要创建一个自定义解决方案,例如(如@Dinar所述)如果您将用户会话存储在数据库中,那么您可以在满足特定条件时检索并销毁特定用户的会话 - 更改其密码 .