我有两个在相同数据库上运行的cakephp2应用程序,但具有不同的Auth表和相应的$ this-> Auth-> userModel值。 身份验证效果很好,一个应用程序的用户无法登录其他应用程序。
但是......当应用程序使用相同的CAKEPHP会话cookie时,会发生以下情况: 当应用程序“one”的用户登录时,它可以访问应用程序“两个”中的任何受Auth保护的操作!
我可能会使用不同的用户角色和Cookie名称。 但是,为什么Auth组件在检查会话时忽略了Auth-> userModel设置?有没有办法将它配置为在这种情况下正常工作?
提前感谢任何建议。
答案 0 :(得分:11)
如果没有另外配置,AuthComponent会将经过身份验证的用户记录写入CakePHP 2中的Auth.User
会话密钥。But it can be changed:
<强> AuthComponent :: sessionKey 强>
存储当前用户记录的会话密钥名称。如果未指定,则为“Auth.User”。
(在CakePHP 1.3中this was different:Auth.{$userModel name}
)
因此,如果您的应用共享会话(如果Cookie名称与Security.salt
匹配),则会共享登录记录。
有两种可能性来解决这个问题:
只需为您的两个模型设置不同的AuthComponent::sessionKey
即可。这将允许他们单独保留登录用户
为这两个应用配置不同的Cookie名称和Salt,因此他们的会话不能互相覆盖。这可能是更清晰的解决方案,因为它还涵盖了其他会话密钥被重复使用的风险。
答案 1 :(得分: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')
)
);
但是正如这个问题所提到的,两者的会话并不相处并相互覆盖。克服这个问题的最佳方法是什么?
答案 2 :(得分:0)
使用MyDatabaseSession之类的东西扩展Model / Datasource / Session / DatabaseSession.php会话处理程序,并覆盖write和read方法。也许只需复制两种方法的现有代码并添加类似
的内容&#39; APP_ID&#39; =&GT;配置::读取(&#39; App.appId&#39)
到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);
}
}
我不知道您的应用程序,所以您是否将配置数据写入配置数据取决于您,bootstrap或beforeFilter()可能。您应该在会话初始化之前添加它我认为或者您需要重新启动会话或其他内容。我把它留给你看看正确的一点。 :)