Yii2 从用户当前会话远程注销用户会话

Yii2 remote logout a user session from the user current session

我想注销登录到与同一用户的当前会话不同的 browser/environment 的用户会话。类似于此的功能 - https://www.facebook.com/settings?tab=security&section=sessions&view.

Yii2是使用的后端框架。使用 redis 进行会话管理 - yii2-redis。我还保存了保存在数据库中的会话 ID。

我关注了这篇文章 - http://www.codeinphp.com/general/php-code-snippets/remotely-destroy-different-session-php-forced-user-signout/

但是没有成功。

session_id($old_session_id);
session_start(); // This line throws error.
session_destroy();

使用 \Yii::$app->session->destroySession($oldSessionId) 删除 redis 中的键没有注销。

将会话 ID 更改为旧会话 ID 然后销毁会话也没有用。

$currentSessionId = \Yii::$app->session->getId();
\Yii::$app->session->setId($oldSessionId);
\Yii::$app->getSession()->destroy();
\Yii::$app->session->setId($currentSessionId);

如果有人成功地实施了这一点,请分享您的解决方案。此外,如果有任何与此相关的文档可以提供帮助,请提供。

第一个,session_start()必须在session_id()之前调用,并且只调用一次

if (session_status() == PHP_SESSION_NONE) {
   session_start();
}
session_id($old_session_id);
session_destroy();

但是仅仅删除session,如果你允许用户自动登录那是不够的,因为浏览器会使用cookie自动登录。要解决,您必须更改用户 AuthKey - Yii2 使用 AuthKey 来验证用户自动登录。默认情况下,每个用户在用户 table 中只有一个 AuthKey,因此当您更改 AuthKey 用户时,可以在任何地方注销。所以我们要定制。为每个用户会话创建一个 AuthKey,存储在用户 table 之外的某个地方。操作简单:扩展 yii\web\User class 覆盖 afterLogin 函数,为每个登录会话创建 AuthKey。覆盖 validateAuthKey 函数以验证自动登录使用我们的自定义 AuthKey。现在,当你想终止任何用户会话时:kill PHP 会话 id 和 AuthKey 该会话将立即注销。 我一直在为我的项目使用这个解决方案,它工作正常。

根据 Ngo 的回答,我想出了一个效果很好且更容易设置的方法。

1) 为您的用户 table 添加一个 "last_session_id" 字段。

2) 将以下内容添加到您的主控制器:

public function afterAction($action, $result)
{
    $result = parent::afterAction($action, $result);

    if(Yii::$app->user->id)
    {
        //update the user table with last_session_id
        $user = User::find()->where(['id' => Yii::$app->user->id])->one();
        $user->last_session_id = Yii::$app->session->id;
        $user->save(false);
    }

    return $result;
}

3) 将 site/login 操作更改为以下内容:

public function actionLogin()
{
    if (!\Yii::$app->user->isGuest) {
        return $this->goHome();
    }

    $model = new LoginForm();
    if ($model->load(Yii::$app->request->post()) && $model->login()) {

        //delete previous session ID and change auth key
        Yii::$app->session->destroySession(Yii::$app->user->identity->last_session_id);
        $u = \common\models\User::find()->where(['id' => Yii::$app->user->id])->one();
        $u->auth_key = Yii::$app->security->generateRandomString();
        $u->save(false);
        return $this->goBack();
    } else {
        return $this->render('/site/login', [
            'model' => $model,
        ]);
    }
}