Rest 如何根据用户设置规范化组';s角色和请求方法
我正在创建一个沙盒应用程序作为Api平台实践,我有以下问题需要解决:Rest 如何根据用户设置规范化组';s角色和请求方法,rest,api,symfony,api-platform.com,Rest,Api,Symfony,Api Platform.com,我正在创建一个沙盒应用程序作为Api平台实践,我有以下问题需要解决: 让我们考虑用户实体的REST端点: 免责声明在代码示例中,还有一些属性,但整个概念适用于此 集合获取(aka./api/users)仅对管理员用户可用(所有属性都可用,可能我们不包括散列密码) POST-每个人都应该有权访问以下属性:用户名、电子邮件、普通密码(不只是在有人要求时才保留) 修补/放置-这里变得相当棘手:我希望那些具有管理员角色的人能够访问用户名、电子邮件和密码字段。而那些拥有者只能更改明文密码 删除-只有角色管
让我们考虑用户实体的REST端点:
免责声明在代码示例中,还有一些属性,但整个概念适用于此
集合获取(aka./api/users)仅对管理员用户可用(所有属性都可用,可能我们不包括散列密码)
POST-每个人都应该有权访问以下属性:用户名、电子邮件、普通密码(不只是在有人要求时才保留)
修补/放置-这里变得相当棘手:我希望那些具有管理员角色的人能够访问用户名、电子邮件和密码字段。而那些拥有者只能更改明文密码
删除-只有角色管理员和所有者可以删除
我将从资源配置开始
resources:
App\Entity\User:
# attributes:
# normalization_context:
# groups: ['read', 'put', 'patch', 'post', 'get', 'collection:get']
# denormalization_context:
# groups: ['read', 'put', 'patch', 'post', 'get', 'collection:get']
collectionOperations:
get:
security: 'is_granted("ROLE_ADMIN")'
normalization_context: { groups: ['collection:get'] }
post:
normalization_context: { groups: ['admin:post', 'post'] }
itemOperations:
get:
normalization_context: { groups: ['admin:get', 'get'] }
security: 'is_granted("ROLE_ADMIN") or object == user'
put:
normalization_context: { groups: ['admin:put', 'put'] }
security: 'is_granted("ROLE_ADMIN") or object == user'
patch:
normalization_context: { groups: ['admin:patch', 'patch'] }
security: 'is_granted("ROLE_ADMIN") or object == user'
delete:
security: 'is_granted("ROLE_ADMIN") or object == user'
下面是序列化程序配置
App\Entity\User:
attributes:
username:
groups: ['post', 'admin:put', 'admin:patch', 'collection:get', 'get']
email:
groups: ['post', 'admin:put', 'admin:patch', 'collection:get', 'get']
firstName:
groups: ['post', 'admin:put', 'admin:patch', 'collection:get', 'get']
lastName:
groups: ['post', 'admin:put', 'admin:patch', 'collection:get', 'get']
plainPassword:
groups: ['post', patch]
createdAt:
groups: ['get', 'collection:get']
lastLoginDate:
groups: ['get', 'collection:get']
updatedAt:
groups: ['collection:get']
这是上下文组生成器(注册为服务,如API平台文档中所述
<?php
namespace App\Serializer;
use Symfony\Component\HttpFoundation\Request;
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
final class AdminContextBuilder implements SerializerContextBuilderInterface
{
private $decorated;
private $authorizationChecker;
public function __construct(SerializerContextBuilderInterface $decorated, AuthorizationCheckerInterface $authorizationChecker)
{
$this->decorated = $decorated;
$this->authorizationChecker = $authorizationChecker;
}
public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array
{
$context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
switch($request->getMethod()) {
case 'GET':
$context['groups'][] = 'admin:get';
break;
case 'POST':
$context['groups'][] = 'admin:post';
case 'PUT':
$context['groups'][] = 'admin:put';
case 'PATCH':
$context['groups'][] = 'admin:patch';
}
}
return $context;
}
}
在调查文档、浏览youtube以及最重要的是对上述用户资源进行实验之后,我想出了解决方案
让我们再次从配置开始:
resources:
App\Entity\User:
collectionOperations:
get:
security: 'is_granted("ROLE_ADMIN")'
normalization_context: { groups: ['collection:get'] }
denormalization_context: { groups: ['collection:get'] }
post:
normalization_context: { groups: ['post'] }
denormalization_context: { groups: ['post'] }
itemOperations:
get:
normalization_context: { groups: ['get'] }
security: 'is_granted("ROLE_ADMIN") or object == user'
patch:
normalization_context: { groups: ['patch'] }
denormalization_context: { groups: ['patch'] }
security: 'is_granted("ROLE_ADMIN") or object == user'
delete:
security: 'is_granted("ROLE_ADMIN") or object == user'
起始点之间的主要区别在于,永远不应在操作组中声明管理操作,因为它们将默认添加到上下文中。
接下来是属性组,我们在其中定义某些属性上可用的所有操作
App\Entity\User:
attributes:
id:
groups: ['get', 'collection:get']
username:
groups: ['post', 'admin:patch', 'get', 'collection:get']
email:
groups: ['post', 'admin:patch', 'get', 'collection:get']
plainPassword:
groups: ['post', 'patch', 'collection:get']
firstName:
groups: ['post', 'patch', 'get', 'collection:get']
lastName:
groups: ['post', 'get', 'collection:get']
createdAt:
groups: ['get', 'collection:get']
lastLoginDate:
groups: ['get', 'collection:get']
updatedAt:
groups: ['collection:get']
这与问题中的完全相同,我们需要配置的唯一一件事是哪些操作需要成为“管理员”。这可以根据您的需要进行更改,无论您编写博客、库、商店或其他什么,并且需要在API上对每个角色执行一些自定义操作。
最后是自定义上下文生成器
<?php
namespace App\Serializer;
use Symfony\Component\HttpFoundation\Request;
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
final class AdminContextBuilder implements SerializerContextBuilderInterface
{
private $decorated;
private $authorizationChecker;
public function __construct(SerializerContextBuilderInterface $decorated, AuthorizationCheckerInterface $authorizationChecker)
{
$this->decorated = $decorated;
$this->authorizationChecker = $authorizationChecker;
}
public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array
{
$context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
$context['groups'][] = 'admin:patch';
$context['groups'][] = 'admin:post';
$context['groups'][] = 'admin:get';
}
return $context;
}
}