gpt4 book ai didi

CakePHP 4.1 用户实体作为授权身份关联字段

转载 作者:行者123 更新时间:2023-12-03 08:39:15 25 4
gpt4 key购买 nike

我刚刚在 CakePHP 4.1 中创建了一个非常小的项目,主要模仿 CMS 教程,并且想要实现一个相当简单的逻辑。使用授权模块,我希望允许用户A能够查看用户B(如果1)他们实际上是同一用户 (A = B) 或 2) 如果 A 是管理员。

有两个数据库表 - usersuser_typesusers 有一个到 user_types 的外键 user_type_id

这种关系在代码中体现为:

##### 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-as-the-identity 。从代码角度看,这看起来像:

##### 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;
}
}

但是,我无法在 UserPolicy.php 文件中获取身份 User 来填充 user_type 字段。当我从 Controller 调用 $this->Authorization->authorize() 时,似乎会发生一些幕后的魔法,我在 Controller 中显式传递资源及其用户类型(因为我已经构造了它)与 '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 选项时,您还需要指定解析器类名称,因为默认情况下它只是一个字符串,而不是与新配置合并的数组!

另请参阅

关于CakePHP 4.1 用户实体作为授权身份关联字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63057543/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com