如何解决为 collectionOperations
是否可以在实体上实现 ApiResource 安全性,以便没有实体 id 的 GET 请求(即集合操作)仅返回与当前经过身份验证的用户匹配的项目(或者,为此目的,必须返回任何其他规则)针对每个实体进行检查)?
到目前为止我的实现:
/**
* @ORM\Entity(repositoryClass=UserRepository::class)
* @ORM\Table(name="`user`")
* @ApiResource(
* attributes={"security"="is_granted('ROLE_USER')"},* collectionoperations={"get"={"security"="is_granted('ROLE_ADMIN') or object == user"}},* itemOperations={"get"={"security"="is_granted('ROLE_ADMIN') or object == user"}},* )
*/
class User implements UserInterface
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id;
// ...
}
上面的代码适用于项目操作,但不适用于集合操作符,即假设用户 id。 1(不是管理员)已通过身份验证:
- GET
/api/user/1
使用用户 #1 数据返回 200 OK(根据需要) - GET
/api/user/2
返回 403 FORBIDDEN(根据需要,用户 1 不应能够获取其他用户的数据)。 - GET
/api/user
返回 403 FORBIDDEN(NOT 根据需要,期望的行为将返回一个列表,该列表仅包含通过规则的实体,即用户 #1 的数据)。立>
解决方法
为此使用 Doctrine Extension。这不是安全问题,您不想限制对资源的访问,而是要修改返回的结果。
例如,匆忙修改链接文档上的示例:
final class CurrentUserExtension implements QueryCollectionExtensionInterface
{
public function __construct(private Security $security)
{
}
public function applyToCollection(QueryBuilder $queryBuilder,QueryNameGeneratorInterface $queryNameGenerator,string $resourceClass,string $operationName = null): void
{
if (User::class !== $resourceClass
|| $this->security->isGranted('ROLE_ADMIN')
|| null === $user = $this->security->getUser())
{
return;
}
$rootAlias = $queryBuilder->getRootAliases()[0];
$queryBuilder->andWhere(sprintf('%s.id = :current_user',$rootAlias));
$queryBuilder->setParameter('current_user',$user->getId());
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。