You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API Platform:如何在GET集合操作中以Security作为过滤条件?

解决方案:为API Platform集合GET操作实现条目级权限校验

针对你的需求,无需重写整个DataProvider,以下两种方案可以实现集合GET操作的条目级MESSAGE_VIEW权限校验:

方法一:使用PostRead事件监听器过滤结果

该方案在数据读取完成后,对结果集进行过滤,移除用户无权限的条目,无需修改查询逻辑。

步骤1:创建事件订阅器

namespace App\EventListener;

use ApiPlatform\Core\EventListener\EventPriorities;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Security;

class MessageCollectionFilterSubscriber implements EventSubscriberInterface
{
    private $security;

    public function __construct(Security $security)
    {
        $this->security = $security;
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::VIEW => ['filterMessageCollection', EventPriorities::POST_READ],
        ];
    }

    public function filterMessageCollection(ViewEvent $event)
    {
        $request = $event->getRequest();
        // 仅针对Message集合的GET操作生效
        if ('api_messages_get_collection' !== $request->get('_route')) {
            return;
        }

        $data = $event->getControllerResult();
        if (!is_iterable($data)) {
            return;
        }

        $filteredItems = [];
        foreach ($data as $item) {
            if ($this->security->isGranted('MESSAGE_VIEW', $item)) {
                $filteredItems[] = $item;
            }
        }

        $event->setControllerResult($filteredItems);
    }
}

步骤2:注册订阅器

在config/services.yaml中添加配置:

App\EventListener\MessageCollectionFilterSubscriber:
    tags:
        - { name: kernel.event_subscriber }

方法二:自定义Doctrine ORM过滤器(推荐)

该方案直接在数据库查询阶段过滤无权限条目,性能更优,避免读取不必要的数据。

步骤1:创建自定义过滤器

namespace App\Filter;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Security\Core\Security;

class MessageViewPermissionFilter extends AbstractFilter
{
    private $security;

    public function __construct(Security $security)
    {
        $this->security = $security;
    }

    protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
    {
        // 仅对集合GET操作生效
        if ('get_collection' !== $operationName) {
            return;
        }

        $currentUser = $this->security->getUser();
        if (!$currentUser) {
            // 未登录用户直接返回空结果
            $queryBuilder->andWhere('1 = 0');
            return;
        }

        // 替换为你的实际权限判断逻辑(比如Message与User的关联规则)
        $rootAlias = $queryBuilder->getRootAliases()[0];
        $queryBuilder->andWhere(sprintf('%s.owner = :currentUser', $rootAlias))
            ->setParameter('currentUser', $currentUser);
    }

    public function getDescription(string $resourceClass): array
    {
        // 无需暴露公共过滤参数,返回空数组
        return [];
    }
}

步骤2:配置实体与过滤器

更新Message实体的注解,引入过滤器:

/**
 * @ApiResource(
 *     collectionOperations={
 *       "post"={
 *           "security_post_denormalize"="is_granted('MESSAGE_CREATE', object)"
 *       },
 *       "get"={
 *           "security"="is_authenticated()",
 *           "filters"={"message_view_permission"}
 *       }
 *     },
 *     itemOperations={
 *        "get"={"security"="is_granted('MESSAGE_VIEW', object)"},
 *        "patch"={"security"="is_granted('MESSAGE_EDIT', object)"},
 *        "delete"={"security"="is_granted('MESSAGE_DELETE', object)"},
 *        "put"={"security"="is_granted('MESSAGE_REPLACE', object)"}
 *     }
 * )
 * @ApiFilter(MessageViewPermissionFilter::class, properties={})
 */
class Message
{
    // ... 实体字段与逻辑
}

步骤3:注册过滤器

在config/services.yaml中添加配置:

App\Filter\MessageViewPermissionFilter:
    tags:
        - { name: api_platform.filter, id: 'message_view_permission' }

内容的提问来源于stack exchange,提问作者Yann Chabot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:00:47