php Laravel 5注销特定用户

bjg7j2ky  于 2023-03-28  发布在  PHP
关注(0)|答案(7)|浏览(210)

在我的laravel 5应用程序中,有一个功能允许管理员角色的用户重置非管理员的任何人的密码,但这并不强制用户注销并再次登录。我如何才能强制用户注销一旦他们的密码已被更改?我没有对中间件进行任何更改,以验证用户或任何东西。

yquaqz18

yquaqz181#

我不知道它是否有效,但你可以试试:

// get current user
$user = Auth::user();

// logout user
$userToLogout = User::find(5);
Auth::setUser($userToLogout);
Auth::logout();

// set again current user
Auth::setUser($user);
piztneat

piztneat2#

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

$user = Auth::user();

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

    return redirect('/');
}
bakd9h0s

bakd9h0s3#

试图避免额外的复杂性,如向数据库添加字段,经过一点点调查,我遇到了下一个解决方案。
Idea基于Laravel 5.4,但应该与所有5.x版本兼容。
问题在于Laravel处理注销的方式。https://github.com/laravel/framework/blob/5.4/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php#L154

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方法,我们用我们的自定义覆盖了trait logout(默认的Laravel logout逻辑),几乎相同,但它允许我们注销单个用户。
相同的逻辑适用于我们所有的登录控制器,这取决于我们有多少不同的守卫。
我刚刚完成了这个解决方案,经过快速测试,它似乎工作正常,但请在实施前仔细检查。

xmq68pz9

xmq68pz94#

如果你使用Laravel 5.2,你可以将会话存储引擎改为数据库。在这种情况下,每个会话记录也将包含用户的ID。
所有你需要的只是从数据库中删除相应的行。

bf1o4zei

bf1o4zei5#

查看docs,似乎没有任何内置函数,类似的请求有been proposed,它也描述了跟踪在多个设备上打开多个会话的单个用户的问题。
我相信你将需要创建一个自定义的解决方案,例如(如@第纳尔所提到的)如果你在数据库中存储用户会话,那么当满足某个条件时,你可以检索并销毁特定用户的会话-更改他们的密码。

bz4sfanl

bz4sfanl6#

$findUser = User::find($userId); \Session::getHandler()->destroy($findUser->session_id);
拉腊维尔5.5

a14dhokn

a14dhokn7#

我以前遇到过这个问题,@vkovic解释得很好,当使用guard()-〉logout()销毁每个守护会话时。我解决这个问题的方法是不同的,我仍然使用默认的注销过程,但我恢复了我想要保留的守护会话。

public function logout(Request $request)
{
    // save the teams sessions if exist
    if (auth('teams')->user()) {
        $teams_session_hash = 'login_teams_'.sha1('Illuminate\Auth\SessionGuard');
    }

    $this->guard()->logout();

    $request->session()->invalidate();
    $request->session()->regenerateToken();

    // restores the teams sessions if exist
    if (isset($teams_session_hash) && $teams_session_hash) {
        $request->session()->put($teams_session_hash, auth('teams')->id());
    }

    return $this->loggedOut($request) ?: redirect('/');
}

相关问题