13

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

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

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

在此先感谢您的任何建议。

4

3 回答 3

11

如果没有另外配置,AuthComponent 会将经过身份验证的用户记录写入Auth.UserCakePHP 2 中的会话密钥。但可以更改:

AuthComponent::sessionKey

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

(在 CakePHP 1.3中这是不同Auth.{$userModel name}的:)

因此,如果您的应用程序共享一个会话,他们这样做,如果 cookie 名称和Security.salt匹配,登录记录将被共享。

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

分开登录

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

分开会话

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

于 2012-05-28T14:44:23.960 回答
3

我有一个类似的问题,这就是为什么我在这个问题上开始赏金。基本上,我有一个应用程序的面向公众的部分,它允许用户从一个表登录,而应用程序的一个管理部分允许管理员使用不同的表登录。我的 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')
    )
);

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

于 2012-05-27T04:05:27.030 回答
0

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

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

到 read() 条件并在 write 方法中执行相同的操作。并且不要忘记将该字段添加到您的会话数据库架构中并配置会话以使用您的处理程序

<?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() 可能。我认为您应该在会话初始化之前添加它,否则您需要重新启动会话或其他东西。我把它留给你看正确的观点。:)

于 2012-05-28T06:52:41.207 回答