微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为 collectionOperations

如何解决为 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 举报,一经查实,本站将立刻删除。