cakephp - CakePHP 4.1 用户实体作为授权身份相关字段
问题描述
我刚刚在 CakePHP 4.1 中创建了一个非常小的项目,主要模仿 CMS 教程,并且想要实现一个相当简单的逻辑。使用该模块,如果 1) 他们实际上是同一个用户 ( ) 或 2) 如果是管理员,Authorization
我希望允许用户A
能够访问view
该用户。B
A = B
A
有两个数据库表 -users
和user_types
. users
有一个外user_type_id
键user_types
。
这种关系在代码中体现为:
##### in UsersTable.php #####
class UsersTable extends Table {
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->belongsTo('UserTypes');
$this->addBehavior('Timestamp');
}
//...
}
##### in UserTypesTable.php #####
class UserTypesTable extends Table {
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('user_types');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->hasMany('Users');
}
//...
}
在UsersController.php
我有:
public function view($id = null)
{
$user = $this->Users->get($id, [
'contain' => ['UserTypes'],
]);
$this->Authorization->authorize($user);
$this->set(compact('user'));
}
并在UserPolicy.php
:
use App\Model\Entity\User;
class UserPolicy
{
public function canView(User $user, User $resource)
{
// TODO: allow view if $user and $resource are the same User or if $user is an admin
//
// My problem is that here $user->user_type is NULL
// while $resource->user_type is populated correctly
}
}
上面摘录中的代码注释显示了我的问题所在。我不知道如何填充$user
其user_type
字段以检查他们是否是管理员。
作为我努力的一部分,我已将 User 类设置为授权身份,遵循这篇文章:https ://book.cakephp.org/authorization/2/en/middleware.html#using-your-user-class -作为身份。代码方面,这看起来像:
##### relevant part of Application.php #####
$middlewareQueue
->add(new AuthenticationMiddleware($this))
->add(new AuthorizationMiddleware($this, [
'identityDecorator' => function(\Authorization\AuthorizationServiceInterface $auth, \Authentication\IdentityInterface $user) {
return $user->getOriginalData()->setAuthorization($auth);
}
]));
##### User.php #####
namespace App\Model\Entity;
use Authentication\PasswordHasher\DefaultPasswordHasher;
use Authorization\AuthorizationServiceInterface;
use Authorization\Policy\ResultInterface;
use Cake\ORM\Entity;
/**
* User Entity
*
* @property int $id
* @property string $email
* @property string $password
* @property string|null $name
* @property \App\Model\Entity\UserType $user_type
* @property \Cake\I18n\FrozenTime|null $created
* @property \Cake\I18n\FrozenTime|null $modified
* @property \Authorization\AuthorizationServiceInterface $authorization
*/
class User extends Entity implements \Authorization\IdentityInterface, \Authentication\IdentityInterface
{
protected $_accessible = [
'email' => true,
'password' => true,
'name' => true,
'created' => true,
'modified' => true,
];
/**
protected $_hidden = [
'password',
];
protected function _setPassword(string $password) : ?string
{
if (strlen($password) > 0) {
return (new DefaultPasswordHasher())->hash($password);
}
}
/**
* @inheritDoc
*/
public function can(string $action, $resource): bool
{
return $this->authorization->can($this, $action, $resource);
}
/**
* @inheritDoc
*/
public function canResult(string $action, $resource): ResultInterface
{
return $this->authorization->canResult($this, $action, $resource);
}
/**
* @inheritDoc
*/
public function applyScope(string $action, $resource)
{
return $this->authorization->applyScope($this, $action, $resource);
}
/**
* @inheritDoc
*/
public function getOriginalData()
{
return $this;
}
/**
* Setter to be used by the middleware.
* @param AuthorizationServiceInterface $service
* @return User
*/
public function setAuthorization(AuthorizationServiceInterface $service)
{
$this->authorization = $service;
return $this;
}
/**
* @inheritDoc
*/
public function getIdentifier()
{
return $this->id;
}
}
但是,我无法获得文件中的身份User
来填充UserPolicy.php
该字段。user_type
当我从控制器调用时,似乎发生了一些幕后的魔法$this->Authorization->authorize()
,在控制器中我明确地传递了资源及其用户类型(因为我已经用它构建了它,'contain' => ['UserTypes']
但是身份用户是由Authorization
模块自动填充的。有人可以帮我吗找到一种将关联表数据带入授权策略的身份用户的方法?
注意:我已经捏造了代码以使其像这样工作:
##### in UserPolicy.php #####
use App\Model\Entity\User;
class UserPolicy
{
public function canView(User $user, User $resource)
{
$user = \Cake\Datasource\FactoryLocator::get('Table')->get('Users')->get($user->id, ['contain' => ['UserTypes']]);
// Now both $user->user_type and $resource->user_type are correctly populated
}
}
然而,这感觉非常“hacky”,而不是它应该是的方式,所以我最初的问题仍然存在。
解决方案
身份由相关标识符的解析器获取。在 CMS 教程的情况下,Password
这是默认使用ORM
解析器的标识符。
可以将ORM
解析器配置为使用自定义查找器,以防您需要控制查询以获取用户,这就是您应该为UserTypes
关联添加包含的地方。
在您UsersTable
添加这样的查找器:
public function findForAuthentication(\Cake\ORM\Query $query, array $options): \Cake\ORM\Query
{
return $query->contain('UserTypes');
}
并配置标识符的解析器以使用该查找器,如下所示:
$service->loadIdentifier('Authentication.Password', [
'resolver' => [
'className' => 'Authentication.Orm',
'finder' => 'forAuthentication',
],
'fields' => [
'username' => 'email',
'password' => 'password',
]
]);
在覆盖选项时,您还需要指定解析器类名称resolver
,因为默认情况下它只是一个字符串,而不是与新配置合并的数组!
也可以看看
推荐阅读
- android - 此服务需要以下应用程序的最新版本 华为移动服务 hms core
- c# - 如何使用嵌套属性使用 LINQ 对列表进行排序
- java - Java BigInteger 源代码性能基准测试
- spring-boot - 如何从多个应用程序实例同时运行相同的弹簧批处理作业
- android - 在 Android 中,如何为缓存的图像设置 Glide 签名(缓存到期)
- flutter - 使用前缀设置 TextFormField 的宽度大小以匹配普通 TextFormField
- pycharm - 在现有 conda 环境中具有相同 python 可执行文件的解释器
- python - TypeError:图像数据的尺寸无效
- android - 你怎么称呼这种类型的通知(?),它在 Flutter 中可用吗?
- python - 如何将 [N * 1 * M] 值仅分配给 [N*M*M] 数组的对角线?