如何在cakePHP3中删除特定用户的会话?

如何在cakePHP3中删除特定用户的会话?,php,cakephp-3.0,Php,Cakephp 3.0,我需要实现的是管理员能够删除给定用户的会话以强制重新登录。例如,当用户权限发生更改时,这会很方便。如何将会话和用户绑定在一起,以便其他用户可以访问该数据 我正在使用数据库会话存储,因此从数据库中删除记录将导致强制重新登录。身份验证也基于Auth组件 以下是我的一些相关配置: $this->loadComponent('Auth', [ 'loginAction' => [ 'controller' => 'Auth',

我需要实现的是管理员能够删除给定用户的会话以强制重新登录。例如,当用户权限发生更改时,这会很方便。如何将会话和用户绑定在一起,以便其他用户可以访问该数据

我正在使用数据库会话存储,因此从数据库中删除记录将导致强制重新登录。身份验证也基于
Auth
组件

以下是我的一些相关配置:

$this->loadComponent('Auth', [
            'loginAction' => [
                'controller' => 'Auth',
                'action' => 'login'
            ],
            'loginRedirect' => "/home",
            'logoutRedirect' => [
                'controller' => 'Auth',
                'action' => 'login'
            ],

            'authError' => "You have no permissions to access resource ${url}. Contact system administrator.",
            'storage' => 'Session',
            'authenticate' => [
                'Form' => [
                    'userModel' => 'User',
                    'finder' => 'user',
                    'fields' => ['username' => 'name', 'password' => 'password']
                ]
            ],
            'authorize' => ["Controller"]
        ]);
和会话存储:

   'Session' => [
        'defaults' => 'database',
]
下面我已经标记了我将数据库更新代码放在哪里。不幸的是,在登录执行之后,会话被“重新验证”,因此ID发生了变化。总之,在重定向后,登录操作中所做的更改不可见

登录操作:

public function login()
{
    $form = new LoginForm();
    if ($this->request->is('post')) {
        if ($form->validate($this->request->data)) {
            $user = $this->Auth->identify();
            if ($user) {
                $this->Auth->setUser($user);
                // here would be good place to update the database 
                return $this->redirect($this->Auth->redirectUrl());
            } else {
                $this->Flash->error("Invalid security credentials provided");
            }
        } else {
            $this->Flash->error("Invalid login form");
        }
    }
    $this->set('loginForm', $form);
}

@ndm感谢您的宝贵评论和精确定位。

感谢@ndm的评论,我找到了(很可能)可行的解决方案。我不得不在会话数据保存过程中注入一些代码。为此,我使用了定制的
SessionHandler
和PHP的
Cloasure
作为回调函数

class UserSession extends DatabaseSession
{
    public $callback;
    public function write($id, $data)
    {
        $result = parent::write($id, $data);
        if ($this->callback) {
            call_user_func($this->callback,$id);
        }
        return $result;
    }
}
以及登录操作

        $user = $this->Auth->identify();
        if ($user) {
            $this->Auth->setUser($user);
            /**  @var UserTable $model */
            $model = $this->loadModel("User");
            $handler = $this->Session->engine();
            /** @var UserSession $handler */
            $handler->callback = function ($id) use ($model, $user) {
                $model->updateSession($id, $user['id']);
            };
            return $this->redirect($this->Auth->redirectUrl());
        }
这样,在将会话数据刷新到数据库中之后,数据库中的会话行将被更新


现在我可以查询给定用户的所有会话,并在需要时删除它们,强制该用户重新登录。回调只在用户登录时调用一次,这也是我在每次http请求期间优化和避免
UPDATE
query db的目标(因为这也是解决方案,但我想避免)

当auth组件写入会话存储时,会话正在被更新,因此,调用
$this->Auth->setUser()
后访问会话ID应该可以工作。你到底试了什么?我完全试了你提到的。在上面的代码中,我在注释所在的位置(在setUser之后)修改了数据库内容,但在重定向或新请求后仍然会被覆盖。您需要更精确一点,最好显示您使用的代码,并解释“被覆盖”的确切含义,用什么数据覆盖什么?我试图将用户绑定到会话的内容与此无关。这里的相关部分是,在登录后的下一个请求中(通过代码重定向或直接从浏览器请求),将创建新会话(会话数据在数据库中被覆盖)。我在问题中指出,
不幸的是,在登录执行后,会话会“重新验证”,因此ID会更改,这是我的主要障碍。也许我使用的Auth组件是错误的,这是不正常的行为。我不知道;(这可能是相关的,也可能不是。也许你正在做的是导致会话续订,也许你读取了错误的值,等等,谁知道,我不是透视者,我不知道你的代码。你说ID改变了,但你没有解释你是如何测试的,所以我知道你甚至可能以错误的方式测试东西。会话ID n通常情况下,在
setUser()
之后不应该更改,事实上对我来说也不应该更改,所以这就是我现在所能说的,我不能从这里调试你的应用程序,我只能告诉你在这里显示的内容,因此我要求你提供详细信息。“…如果需要,请删除它们,强制该用户重新登录…”如何在DB中使用类似于
操作符的
查找会话是我已经在使用并希望避免的事情。我认为我不理解您的问题。您是否要查询DB。您将使用什么操作符来查找会话取决于您。我只是想找到是否有更好的方法从DB中查找用户会话并删除(或过期)记录。在我的情况下,users表中有一列控制是否允许用户登录。如果我禁用(已登录的用户),我想删除他的会话,以便强制他注销。目前,我通过使用查找用户的会话数据来完成此操作(以下是通过Cake翻译的SQL):
从'my_sessions'表中选择'Session`.'id`作为'Session`,其中'Session`.'data`类似于'%s:2:id;s:3:123'%'和'Session`.`expiry`>=**current epoch**
。我不必按字符串内容匹配进行搜索,而是按用户id进行搜索,因为用户id是其中的一列。您所做的可能工作正常,但效率低下,因为字符串部分没有使用索引。听起来相当合理。我将尝试通过向DB架构添加一列,然后在popul中进行搜索在
MySessionTable.php
model的
beforeSave()
(是的,我有一个
mysessions\u表的模型,我在其中定义了两个方便的函数)。让我们看看它是如何运行的。谢谢。