Symfony Workflow:能否按用户角色与文章状态配置访问权限?
问题:能否通过Symfony Workflow配置控制实体访问权限?
你当前的Symfony工作流配置如下:
framework: workflows: post_publishing: type: 'state_machine' marking_store: type: 'method' property: 'state' supports: - App\Entity\Post initial_marking: pending places: - pending - draft - published - archived transitions: to_draft: guard: "is_granted('ROLE_ADMIN')" from: pending to: draft to_publish: guard: "is_granted('ROLE_USER')" from: draft to: published to_archived: guard: "is_granted('ROLE_USER')" from: [published, draft] to: archived
你的需求是:
- 未认证用户仅能查看已发布文章
- 认证用户(ROLE_USER)可查看草稿与已发布文章
- 管理员(ROLE_ADMIN)可查看所有状态的文章
首先明确:Workflow Bundle的配置是用来管控状态转换权限的(比如谁能把草稿改成已发布),没法直接在Workflow配置里实现实体的访问权限控制。实体访问权限属于数据层面的授权逻辑,应该用Symfony Security组件的自定义Voter来实现,结合文章的状态和用户角色即可。
下面是具体的实现步骤:
1. 创建自定义Voter
生成一个PostVoter类,用来处理文章的访问权限判断:
// src/Security/Voter/PostVoter.php namespace App\Security\Voter; use App\Entity\Post; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\User\UserInterface; class PostVoter extends Voter { // 定义要检查的权限标识 public const VIEW = 'VIEW_POST'; protected function supports(string $attribute, mixed $subject): bool { // 只处理VIEW_POST权限和Post实体的校验 return $attribute === self::VIEW && $subject instanceof Post; } protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool { $user = $token->getUser(); // 未认证用户仅允许查看已发布文章 if (!$user instanceof UserInterface) { return $subject->getState() === 'published'; } // 管理员直接拥有所有文章的查看权限 if ($token->isGranted('ROLE_ADMIN')) { return true; } // 普通认证用户允许查看草稿和已发布状态的文章 $allowedStates = ['draft', 'published']; return in_array($subject->getState(), $allowedStates); } }
2. 在业务逻辑中使用权限校验
在控制器获取文章列表时,建议结合角色和状态做数据库层面的筛选(性能更优):
// 控制器示例 public function index(EntityManagerInterface $em, AuthorizationCheckerInterface $authChecker): Response { $qb = $em->createQueryBuilder() ->select('p') ->from(Post::class, 'p'); $user = $this->getUser(); if (!$user) { // 未认证用户仅查询已发布文章 $qb->where('p.state = :state') ->setParameter('state', 'published'); } elseif (!$authChecker->isGranted('ROLE_ADMIN')) { // 普通认证用户查询草稿和已发布文章 $qb->where('p.state IN (:states)') ->setParameter('states', ['draft', 'published']); } // 管理员无需过滤,直接查询所有文章 $posts = $qb->getQuery()->getResult(); return $this->render('post/index.html.twig', [ 'posts' => $posts, ]); }
在Twig模板中单独判断单篇文章的访问权限:
{% for post in posts %} {% if is_granted('VIEW_POST', post) %} <div class="post-item"> <h3>{{ post.title }}</h3> <p>{{ post.content }}</p> </div> {% endif %} {% endfor %}
内容的提问来源于stack exchange,提问作者Shoooryuken
相关产品推荐
相关产品推荐

