我需要实现的是让管理员可以删除给定用户的会话以强制重新登录。例如,当用户权限更改时,这可以派上用场。如何将会话和用户绑定在一起,以便其他用户可以访问该数据?
我正在使用数据库会话存储,因此从数据库中删除记录将导致强制重新登录。此外,身份验证基于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);
}
答案 0 :(得分:0)
@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
查询db的目标(因为那也是解决方案,但我想避免这种情况)