首页 文章

Laravel 5注销特定用户

提问于
浏览 16
2

在我的laravel 5应用程序中,有一个功能允许具有admin角色的用户重置任何非管理员的密码,但是这并不会强制该用户注销并再次登录 . 一旦密码更改,我该如何强制用户注销?我没有对中间件进行任何更改来验证用户或任何东西 .

5 回答

  • 7

    如果使用Laravel 5.2,则可以将会话存储引擎更改为数据库 . 在这种情况下,每个会话记录也将包含用户的ID .

    您只需要从数据库中删除相应的行 .

  • 2

    试图避免额外的复杂性,如向db添加字段,经过一些调查,我遇到了下一个解决方案 .

    Idea基于Laravel 5.4,但应与所有5.x版本兼容 .

    问题在于Laravel处理注销的方式 . 正如我们在_1742621中看到的那样_

    public function logout(Request $request)
    {
        $this->guard()->logout();
    
        $request->session()->invalidate();
    
        return redirect('/');
    }
    

    $request->session()->invalidate(); 行是刷新请求会话数据并重新生成ID . 所以在这之后,如果我们启用了多个防护,他们都将被注销 .

    我们的想法是只删除一个会话密钥,该密钥对应于我们正在注销的当前用户 . 如果我们检查我们的会话(注意“login_ *”键),当来自不同警卫的用户登录时,我们将得到如下内容:

    array:5 [▼
        "_token" => "qB4zDqDbknpO7FOrfNQ3YuFxpnji95uamJflxSkV"
        "_previous" => array:1 [▶]
        "_flash" => array:2 [▶]
        "login_admin_51ba36addc2b2f9401580f014c7f58ea4e30989d" => 74
        "login_user_51ba36addc2b2f9401580f014c7f58ea4e30989d" => 23
    ]
    

    我们只需要删除这个单独的相应密钥,而不是刷新整个会话 . 要获取当前保护会话名称(上面示例中的会话密钥),我们可以使用guard方法:https://github.com/laravel/framework/blob/5.4/src/Illuminate/Auth/SessionGuard.php#L622

    现在我们拥有执行此任务所需的一切 . 以下是我目前正在进行的项目中的示例:

    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 ...
    
    }
    

    使用 LoginController::logout 方法,我们用我们的自定义覆盖特征注销(默认的Laravel注销逻辑),几乎相同,但这将允许我们注销单个用户 .

    同样的逻辑适用于我们所有的登录控制器,具体取决于我们拥有多少不同的防护 .

    我刚刚完成了这个解决方案,经过快速测试后似乎工作正常,但请在实施前仔细检查 .

  • 1

    我不知道它是否会起作用,但您可以尝试:

    // get current user
    $user = Auth::user();
    
    // logout user
    $userToLogout = User::find(5);
    Auth::setUser($userToLogout);
    Auth::logout();
    
    // set again current user
    Auth::setUser($user);
    
  • 0

    我认为最快的解决方案是在用户数据库表中添加一个标志,例如布尔列 to_logout ,并在Auth中间件中添加类似此代码的内容 .

    $user = Auth::user();
    
    if($user->to_logout){
        Auth::logout();
        $user->update(['to_update' => 0]);
    
        return redirect('/');
    }
    
  • 0

    查看docs,似乎没有任何内置函数,类似的请求been proposed也描述了跟踪在多个设备上打开多个会话的单个用户的问题 .

    我相信您需要创建一个自定义解决方案,例如(如@Dinar所述)如果您将用户会话存储在数据库中,那么您可以在满足特定条件时检索并销毁特定用户的会话 - 更改其密码 .

相关问题