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

Symfony 2.8升5.4:无ROLE_前缀角色is_granted权限拒绝问题

问题分析与解决方案

你的核心问题是:Symfony 5.4的默认RoleVoter只识别ROLE_前缀的权限属性,而你的自定义CustomVoter因为逻辑限制,无法处理MODULE_开头的权限检查,导致is_granted('MODULE_TRAINING')返回拒绝。


自定义Voter的问题点

  1. 构造函数硬编码了$this->prefix = 'ROLE_',忽略了传入参数,且后续逻辑只处理该前缀的属性
  2. supportsAttribute方法仅支持ROLE_开头的属性,导致MODULE_TRAINING这类属性不会被此Voter处理
  3. 默认RoleVoter同样只处理ROLE_前缀,所以MODULE_*类型的权限检查没有对应Voter响应

修复方案:调整自定义Voter逻辑

修改CustomVoter,让它支持匹配任意字符串类型的权限属性(直接对比用户角色列表):

namespace WORD\CoreBundle\Voter;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\CacheableVoterInterface;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;

class CustomVoter implements CacheableVoterInterface
{
    /**
     * {@inheritdoc}
     */
    public function vote(TokenInterface $token, $subject, array $attributes)
    {
        $result = VoterInterface::ACCESS_ABSTAIN;
        $userRoles = $token->getRoleNames();

        foreach ($attributes as $attribute) {
            if (!\is_string($attribute)) {
                continue;
            }

            // 处理ROLE_PREVIOUS_ADMIN的弃用提示
            if ('ROLE_PREVIOUS_ADMIN' === $attribute) {
                trigger_deprecation('symfony/security-core', '5.1', 'The ROLE_PREVIOUS_ADMIN role is deprecated and will be removed in version 6.0, use the IS_IMPERSONATOR attribute instead.');
            }

            $result = VoterInterface::ACCESS_DENIED;
            // 直接检查用户是否拥有该属性对应的角色
            if (in_array($attribute, $userRoles, true)) {
                return VoterInterface::ACCESS_GRANTED;
            }
        }

        return $result;
    }

    public function supportsAttribute(string $attribute): bool
    {
        // 支持所有字符串类型的权限属性
        return true;
    }

    public function supportsType(string $subjectType): bool
    {
        // 支持所有类型的subject(REST控制器无subject,不影响)
        return true;
    }
}

后续配置步骤

  1. 注册Voter:在config/services.yaml中添加Voter的服务标签:
services:
    WORD\CoreBundle\Voter\CustomVoter:
        tags:
            - { name: security.voter }
        # 可选:设置优先级高于默认RoleVoter,确保优先触发
        # priority: 200
  1. 禁用默认RoleVoter(可选):如果不想保留默认RoleVoter的逻辑,在config/packages/security.yaml中禁用它:
security:
    voters:
        - { name: Symfony\Component\Security\Core\Authorization\Voter\RoleVoter, enabled: false }
  1. 验证角色加载:在控制器中临时添加调试代码,确认Token中的角色列表正确:
public function testAction()
{
    $token = $this->get('security.token_storage')->getToken();
    var_dump($token->getRoleNames());
    // 输出内容应包含MODULE_TRAINING
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:01:09