实现collectionOperations的ApiResource安全筛选器规则



是否可以在实体上实现ApiResource安全性,以便没有实体id的GET请求(即收集操作(只返回与当前已验证用户匹配的项(或者,为此,必须针对每个实体检查的任何其他规则(?

到目前为止我的实现:

/**
* @ORMEntity(repositoryClass=UserRepository::class)
* @ORMTable(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
{
/**
* @ORMId
* @ORMGeneratedValue
* @ORMColumn(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的数据(

为此使用条令扩展。这不是安全问题,您不希望限制对资源的访问,而是希望修改返回的结果。

例如,匆忙修改链接文档上的示例:

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());
}
}

最新更新