具有两个模型会话的 Cakephp 身份验证组件

Posted

技术标签:

【中文标题】具有两个模型会话的 Cakephp 身份验证组件【英文标题】:Cakephp auth component with two models session 【发布时间】:2012-05-19 06:30:19 【问题描述】:

我有两个 cakephp2 应用程序在同一个数据库上运行,但是有不同的 Auth 表和不同的 $this->Auth->userModel 值。 身份验证运行良好,一个应用程序的用户无法登录其他应用程序。

但是.. 由于应用程序使用相同的 CAKEPHP 会话 cookie,会发生这种情况: 当应用程序“一”的用户登录时,它可以访问应用程序“二”中的任何受 Auth 保护的操作!

我可能会使用不同的用户角色和 cookie 名称。 但是,为什么 Auth 组件在检查会话时忽略 Auth->userModel 设置?有没有办法将其配置为在这种情况下正常工作?

提前感谢您的任何建议。

【问题讨论】:

我不知道它是否与此有关,但是当 AuthComponent 将用户存储到会话时,它总是使用 User 无论用户模型名称实际上是什么 - 它的硬-编码。 那是错误的@tigrang,至少对于 2.0。 我发誓前几天在查看源代码时看到它是硬编码的 - 应该仔细检查一下,我的错。 请参阅book.cakephp.org/2.0/en/core-libraries/components/… 并且它在 1.3 年前也已修复,这实际上是一个问题 - 在过去。 :) 【参考方案1】:

如果没有另外配置,AuthComponent 会将经过身份验证的用户记录写入 CakePHP 2 中的 Auth.User 会话密钥。But it can be changed:

AuthComponent::sessionKey

存储当前用户记录的会话密钥名称。如果未指定,则为“Auth.User”。

(在 CakePHP 1.3 中 this was different: Auth.$userModel name

因此,如果您的应用共享一个 Session,如果 cookie 名称和 Security.salt 匹配,则将共享登录记录。

解决这个问题有两种可能:

分离登录

只需为您的两个模型设置不同的AuthComponent::sessionKey。这将允许他们单独保留已登录的用户

分离会话

为两个应用程序配置不同的 Cookie 名称和 Salts,因此它们的会话不能相互覆盖。这可能是更简洁的解决方案,因为它还涵盖了其他会话密钥被双重使用的风险。

【讨论】:

会话密钥不会创建新的或不同的会话,而只是更改当前会话中身份验证数据的存储位置。 是的,完全正确。这将防止两个应用程序的身份验证受到干扰。创建一个完全不同的会话是我的第二个解决方案。 您的第一个解决方案成功了!我做了: AuthComponent::$sessionKey = 'Auth.MyCustomModel' 如何在 cakephp 3 中使用会话密钥?【参考方案2】:

我有一个类似的问题,这就是为什么我开始悬赏这个问题。基本上,我有一个应用程序的面向公众的部分,它允许用户从一个表登录,而应用程序的一个管理部分允许管理员使用不同的表登录。我的 AppController 看起来像这样:

public $components = array(
    'Session',
    'Auth' => array(
        'autoRedirect' => false,
        'authenticate' => array(
            'Form' => array(
                'userModel' => 'User'
            )
        ),
        'loginAction' => array('controller' => 'users', 'action' => 'login'),
        'loginRedirect' => array('controller' => 'users', 'action' => 'overview'),
        'logoutRedirect' => array('controller' => 'users', 'action' => 'loggedout')
    )
);

我有另一个 AdminController,我有这个:

public $components = array(
    'Session',
    'Auth' => array(
        'authenticate' => array(
            'CustomForm' => array(
                'userModel' => 'Admin'
            )
        ),
        'loginAction' => array('controller' => 'admin', 'action' => 'login'),
        'loginRedirect' => array('controller' => 'admin', 'action' => 'index'),
        'logoutRedirect' => array('controller' => 'home', 'action' => 'index')
    )
);

但正如在这个问题中提到的那样,两者的会话不会相处并相互覆盖。克服这个问题的最佳方法是什么?

【讨论】:

我很高兴你提出了赏金。在实现这一点时我也学到了一些额外的东西:在AppController 中设置Auth 的范围会产生多个登录的问题。 AppController 中的'scope' => array('User.delete_status' => 0) 未被CustomersController 中的'scope' => array('Customer.delete_status' => 0) 覆盖。相反,它被附加在 Cake 使用的 SQL 查询中,例如 .. WHERE User.delete_status=0 AND Customer.delete_status=0。我不得不将那个位从 AppController 移到 UsersController 中(就像你在各自的控制器中有 Auth 一样)。【参考方案3】:

使用 MyDatabaseSession 之类的东西扩展 Model/Datasource/Session/DatabaseSession.php 会话处理程序并覆盖写入和读取方法。也许只需复制这两种方法的现有代码并添加类似

'app_id' => 配置::read('App.appId')

到 read() 条件并在 write 方法中执行相同操作。并且不要忘记将该字段添加到您的会话数据库架构和configure the session to use your handler。

<?php
App::uses('DatabaseSession', 'Model/Datasource/Session');
class ExtendedDatabaseSession extends DatabaseSession  

    public function read($id) 
        $row = $this->_model->find('first', array(
                'conditions' => array(
                    'app_id' => Configure::read('App.appId'),
                    $this->_model->primaryKey => $id)));

        if (empty($row[$this->_model->alias]['data'])) 
            return false;
        

        return $row[$this->_model->alias]['data'];
    

    public function write($id, $data) 
        if (!$id) 
            return false;
        
        $expires = time() + $this->_timeout;
        $record = compact('id', 'data', 'expires');
        $record[$this->_model->primaryKey] = $id;
        $record['app_id'] = Configure::read('App.appId');
        return $this->_model->save($record);
    

我不知道你的应用程序,所以你是否将应用程序 ID 写入配置数据取决于你,引导程序或 beforeFilter() 可能。我认为您应该在会话初始化之前添加它,否则您需要重新启动会话或其他东西。我把它留给你看正确的观点。 :)

【讨论】:

以上是关于具有两个模型会话的 Cakephp 身份验证组件的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 4 中的多个身份验证会话

使用 CakePHP 'Acl' 组件

cakephp 一个表单,多个模型,不显示一个模型的验证消息

CakePHP 3 Auth注销 - 错误:未找到身份验证适配器“loginAction”

如何在模型中包含 Session 组件? CakePHP

未找到CakePhp 3插件身份验证适配器