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

时间:2016-04-11 14:45:54

标签: php cakephp-3.0

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

我正在使用数据库会话存储,因此从数据库中删除记录将导致强制重新登录。此外,身份验证基于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);
}

1 个答案:

答案 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的目标(因为那也是解决方案,但我想避免这种情况)