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

Spring Boot 3.3:为SUPERADMIN角色绕过@PreAuthorize校验

Spring Boot 3.3 + Spring Security 6.3.3 实现SUPERADMIN绕过@PreAuthorize校验

核心需求

已认证用户若持有SUPERADMIN权限,直接绕过控制器上所有@PreAuthorize的权限校验,无需修改现有控制器代码。


方案一:自定义AccessDecisionVoter(推荐,全局无侵入)

通过自定义投票器,让SUPERADMIN权限的用户直接获得访问权限,优先级高于所有默认校验逻辑。

1. 实现SuperAdminVoter

import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;

public class SuperAdminVoter implements AccessDecisionVoter<Object> {
    private static final String SUPER_ADMIN_AUTHORITY = "SUPERADMIN";

    @Override
    public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
        // 未认证用户直接拒绝
        if (authentication == null || !authentication.isAuthenticated()) {
            return ACCESS_DENIED;
        }

        // 检查是否持有SUPERADMIN权限
        boolean isSuperAdmin = authentication.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .anyMatch(SUPER_ADMIN_AUTHORITY::equals);
        
        if (isSuperAdmin) {
            return ACCESS_GRANTED; // 直接放行,绕过后续校验
        }

        return ACCESS_ABSTAIN; // 无SUPERADMIN权限,交给其他投票器处理
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true; // 支持所有权限配置
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true; // 支持所有控制器类
    }
}

2. 配置全局方法安全,注册自定义投票器

import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;

import java.util.List;

@Configuration
@EnableMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Override
    protected AccessDecisionManager accessDecisionManager() {
        // 将自定义投票器放在最前面,优先执行
        List<AccessDecisionVoter<?>> voters = List.of(
                new SuperAdminVoter(),
                // 保留默认的投票器(处理@PreAuthorize表达式)
                super.accessDecisionManager().getDecisionVoters().toArray(new AccessDecisionVoter[0])
        );
        return new AffirmativeBased(voters);
    }
}

方案二:自定义方法安全表达式根(需修改控制器注解)

适合新项目,通过扩展表达式根,添加全局可用的isSuperAdmin()方法,在@PreAuthorize中直接调用。

1. 自定义表达式处理器

import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

public class SuperAdminExpressionHandler extends DefaultMethodSecurityExpressionHandler {
    private static final String SUPER_ADMIN_AUTHORITY = "SUPERADMIN";

    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
        MethodSecurityExpressionOperations root = super.createSecurityExpressionRoot(authentication, invocation);
        // 注册全局变量isSuperAdmin,判断用户是否为超级管理员
        root.setVariable("isSuperAdmin", () -> 
                authentication.getAuthorities().stream()
                        .map(GrantedAuthority::getAuthority)
                        .anyMatch(SUPER_ADMIN_AUTHORITY::equals)
        );
        return root;
    }
}

2. 注册表达式处理器并修改控制器注解

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;

@Configuration
@EnableMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {

    @Bean
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
        return new SuperAdminExpressionHandler();
    }
}

修改控制器的@PreAuthorize表达式:

@RestController
public class ExampleController {

    @PreAuthorize("isSuperAdmin() || hasAnyAuthority('SOME', 'SOME2')")
    @GetMapping("/test")
    public String test() {
        return "This is a protected endpoint, but for SUPERADMIN everything is allowed";
    }
}

验证效果

  1. 登录持有SUPERADMIN权限的用户,访问/test接口,即使没有SOME或SOME2权限,也能正常返回内容。
  2. 登录无SUPERADMIN权限的用户,必须持有SOME或SOME2权限才能访问该接口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:30:52