如何在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表的模型,我在其中定义了两个方便的函数)。让我们看看它是如何运行的。谢谢。