首先,这个问题建立在问答上:Modifying AuthComponent identify method
我正在尝试实现的是使用基于身份验证的SSL基于令牌的API访问。我有API前缀设置和工作,我已成功使用基本身份验证AS LONG为用户名&定义的字段密码在Tokens表中,如下所示:
public function initialize() {
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Auth', [
'authenticate' => [
'Basic' => [
'fields' => ['username' => 'user_id', 'password' => 'app_key_hashed'],
'userModel' => 'Tokens'
]
],
'storage' => 'Memory',
'unauthorizedRedirect' => false
]);
}
最终我想使用用户的电子邮件(来自用户模型)和app_key(来自令牌模型)进行身份验证。阅读完文档(以及上面链接的问题和答案)之后,我觉得我需要使用自定义查找器来实现它。所以我将上面的代码更改为:
public function initialize() {
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Auth', [
'authenticate' => [
'Basic' => [
'fields' => ['username' => 'user.email', 'password' => 'app_key_hashed'],
'userModel' => 'Tokens',
'finder' => 'auth'
]
],
'storage' => 'Memory',
'unauthorizedRedirect' => false
]);
}
并在我的TokensTable.php中包含以下内容:
/**
* Custom finder for Auth
*/
public function findAuth(\Cake\ORM\Query $query, array $options) {
$query->select(['id', 'user_id', 'app_key_hashed', 'Users.email'])
->where(['Tokens.inactive' => 0])
->contain(['Users']);
return $query;
}
当我这样做时,返回消息是:
{
"message": "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Tokens.user.email' in 'where clause'",
"url": "/flight-ops/api/tokens",
"code": 500
}
我觉得问题不在于自定义查找程序查找数据,而是在Auth组件过滤数据时。我对么?我错过了一些简单的事吗?我是否使用自定义查找器咆哮着正确的树?
我正在使用CakePHP 3.2.4。
感谢您的帮助!
以下是我的表格和关系:
class TokensTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('tokens');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id'
]);
}
}
class UsersTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('users');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasOne('Tokens', [
'foreignKey' => 'user_id'
]);
}
}
答案 0 :(得分:2)
首先,感谢Chris在上面的评论中确认我正朝着正确的方向前进。我通过扩展BasicAuthenticate类完成了问题中的任务(实际上,我只是从BaseAuthenticate扩展了一个函数,但我想同时包含BasicAuthenticate,所以我扩展了该类)。
这是我的TokenBasicAuthenticate类:
namespace App\Auth;
use Cake\Auth\BasicAuthenticate;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\ORM\TableRegistry;
class TokenBasicAuthenticate extends BasicAuthenticate{
protected function _query($username)
{
$config = $this->_config;
$table = TableRegistry::get($config['userModel']);
$query = $table->find()
->where([$config['userModel'] . '.inactive' => 0])
->contain([$config['relatedModel']])
->matching($config['relatedModel'], function($q) use ($config, $username) {
return $q->where([$config['fields']['username'] => $username]) ;
});
return $query;
}
}
我还将Auth初始化更改为:
public function initialize() {
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Auth', [
'authenticate' => [
'TokenBasic' => [
'fields' => ['username' => 'Users.email', 'password' => 'app_key_hashed'],
'userModel' => 'Tokens',
'relatedModel' => 'Users',
'finder' => 'auth'
]
],
'storage' => 'Memory',
'unauthorizedRedirect' => false
]);
}
如您所见,我添加了一个额外的字段'relatedModel'来引用相关模型。
它适合我的需求,希望其他人认为这很有用。我确信不止一种方法可以完成这个,随意添加任何有用的东西。