当我想要向具有不同角色的用户授予访问权限时,我因问题而被阻止. 当我在表上下文中存储一些角色时,我为此创建了一个定制投票器.
<?php
namespace App\Security\Voter;
use App\Constants\UserRoles;
use App\Entity\Team;
use App\Entity\User;
use App\Repository\UserTeamRepository;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class TeamVoter extends Voter
{
public function __construct(
private UserTeamRepository $userTeamRepository,
)
{}
/**
* @inheritDoc
*/
protected function supports(string $attribute, mixed $subject): bool
{
if (!in_array($attribute, UserRoles::TEAM_ROLES)) {
return false;
}
return $subject instanceof Team;
}
/**
* @inheritDoc
*/
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
$team = $subject;
if (in_array($attribute, UserRoles::TEAM_RELATED_ROLES)) {
return $this->voteOnTeamRelatedAttribute($attribute, $user, $team);
}
return match($attribute) {
UserRoles::ROLE_TEAM_ADMIN => $this->canEdit($user, $team),
UserRoles::ROLE_TEAM_OWNER => $this->canDelete($user, $team),
default => false,
};
}
private function voteOnTeamRelatedAttribute(string $attribute, User $user, Team $team): bool
{
$userRoles = $this->userTeamRepository->getUserTeamRoles($user, $team->getExternalUuid());
if (!$userRoles) {
return false;
}
return match($attribute) {
UserRoles::ROLE_TEAM_MEMBER_ADMIN => in_array(UserRoles::ROLE_TEAM_MEMBER_ADMIN, $userRoles),
UserRoles::ROLE_TEAM_MEMBER => in_array(UserRoles::ROLE_TEAM_MEMBER, $userRoles),
default => false,
};
}
private function canEdit(User $user, Team $team): bool
{
if ($this->canDelete($user, $team)) {
return true;
}
return in_array(UserRoles::ROLE_TEAM_ADMIN, $user->getRoles());
}
public function canDelete(User $user, Team $team): bool
{
return $team->getOwner() === $user || $team->getCreator() === $user;
}
}
现在,我希望角色为ROLE_TEAM_ADMIN的用户或角色为ROLE_TEAM_MEMBER_ADMIN的用户可以访问该方法(note: ROLE_TEAM_ADMIN更像是一个编辑所有团队的全局角色,而ROLE_TEAM_MEMBER_ADMIN更专注于单个团队,因此自定义投票者判断mm表的内容)
下面是我的控制器中的受保护方法:
#[Route('/rest/team/{externalUuid}/member/add', name: 'add_team_member', methods: ["PUT"])]
#[IsGranted(UserRoles::ROLE_TEAM_ADMIN, subject: 'team'), IsGranted(UserRoles::ROLE_TEAM_MEMBER_ADMIN, subject: 'team')]
public function addTeamMember(Request $request, Team $team): JsonResponse
{
$request = $this->transformJsonBody($request);
...
documentation表示可以配置拨款决策策略,但其缺省值被设置为"肯定",这意味着如果参与拨款的选民之一说可以,那么访问权限就会被授予.
我的问题是,这并不像预期的那样起作用,而是遵循"一致"的决策模式.我已经浏览了这个主题的Stackoverflow,有些人建议使用表达式,但这些答案已经过时了,因为它是针对symfony 5和不建议使用的Sensio安全包的.
在调试它之后,我注意到Symfony\Component\Security\Core\Authorization\Authorization DecisionManager类收集结果(在collectResults方法中),寻找投票者并在此基础上构建其决策,但属性数组始终只有一个属性.
所以我猜我的注释是以错误的方式定义的,但我在文档中找不到任何关于如何处理决策经理的相关示例,显然设置一个又一个注释是不够的.
有没有人有好办法来处理这件事?