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

Spring Boot实现需同时拥有ADMIN和EXECUTIVE角色的接口访问控制

Spring Boot中实现需同时拥有ADMIN和EXECUTIVE角色的接口权限控制

下面是几种实用的实现方案,覆盖不同场景需求:

方法1:使用Spring Security内置表达式(最简便)

Spring Security提供了hasAllRoles()表达式,可直接校验用户是否同时拥有指定的所有角色,注意默认角色前缀为ROLE_,若你的角色未使用该前缀,需先配置关闭或手动添加。

1.1 方法级别注解(推荐)

直接在Controller接口方法上标注@PreAuthorize,精准控制单接口权限:

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SecureController {

    // 要求用户同时拥有ADMIN和EXECUTIVE角色(若角色带ROLE_前缀,需写成hasAllRoles('ROLE_ADMIN', 'ROLE_EXECUTIVE'))
    @PreAuthorize("hasAllRoles('ADMIN', 'EXECUTIVE')")
    @GetMapping("/api/dual-role/secure")
    public String accessDualRoleResource() {
        return "仅同时具备ADMIN和EXECUTIVE角色的用户可访问此接口";
    }
}

若需关闭默认角色前缀,在Security配置类中添加如下配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableMethodSecurity // 开启方法级安全校验
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
            .roleHierarchy(hierarchy -> hierarchy.rolePrefix("")); // 关闭ROLE_前缀
        return http.build();
    }
}

1.2 全局路径配置

若要对一批路径统一设置权限,可在Security配置类中通过路径匹配指定表达式:

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/dual-role/**").access("hasAllRoles('ADMIN', 'EXECUTIVE')")
                .anyRequest().authenticated()
            )
            .roleHierarchy(hierarchy -> hierarchy.rolePrefix(""));
        return http.build();
    }
}

方法2:自定义注解(复用性更强)

如果需要在多个接口复用"同时拥有ADMIN和EXECUTIVE"的权限规则,可自定义注解封装校验逻辑:

步骤1:定义自定义注解

import org.springframework.security.access.prepost.PreAuthorize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("hasAllRoles('ADMIN', 'EXECUTIVE')")
public @interface RequireAdminAndExecutive {
}

步骤2:在接口上使用注解

@RestController
public class SecureController {

    @RequireAdminAndExecutive
    @GetMapping("/api/dual-role/secure")
    public String accessDualRoleResource() {
        return "仅同时具备ADMIN和EXECUTIVE角色的用户可访问此接口";
    }
}

方法3:自定义投票器(复杂场景适配)

若角色校验逻辑需动态调整(比如从数据库读取规则),可自定义AccessDecisionVoter实现更灵活的权限控制:

步骤1:实现投票器

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 DualRoleVoter implements AccessDecisionVoter<Object> {
    private static final String REQUIRED_ROLE_ADMIN = "ADMIN";
    private static final String REQUIRED_ROLE_EXECUTIVE = "EXECUTIVE";
    private static final String RULE_KEY = "ADMIN_AND_EXECUTIVE";

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return RULE_KEY.equals(attribute.getAttribute());
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

    @Override
    public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
        boolean hasAdmin = false;
        boolean hasExecutive = false;

        for (GrantedAuthority authority : authentication.getAuthorities()) {
            if (REQUIRED_ROLE_ADMIN.equals(authority.getAuthority())) hasAdmin = true;
            if (REQUIRED_ROLE_EXECUTIVE.equals(authority.getAuthority())) hasExecutive = true;
        }

        return (hasAdmin && hasExecutive) ? ACCESS_GRANTED : ACCESS_DENIED;
    }
}

步骤2:注册投票器到Security配置

import org.springframework.context.annotation.Bean;
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.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

import java.util.List;

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public AccessDecisionManager accessDecisionManager() {
        return new AffirmativeBased(List.of(new DualRoleVoter()));
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/dual-role/**").access("ADMIN_AND_EXECUTIVE")
                .anyRequest().authenticated()
            )
            .accessDecisionManager(accessDecisionManager());
        return http.build();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:55:25