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

Spring Security配置:如何实现多角色组合的页面访问控制?

解决方案

你遇到的问题核心有两点:原SpEL表达式存在语法错误,以及不同Spring Security版本中access方法的参数类型差异。以下是针对性解决方法:

一、修正SpEL表达式(适用于支持access(String)的版本)

如果你的Spring Security版本在5.7之前,authorizeHttpRequests()的access方法支持传入SpEL字符串,只需补充原表达式中缺失的闭合括号即可:

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .headers().frameOptions().disable()
        .and()
            .authorizeHttpRequests()
                .antMatchers("/aaa/**", "/bbb/**").permitAll()
                .antMatchers("/ccc", "/ddd/**").hasRole("AAA")
                // 修正SpEL语法,补充末尾的闭合括号
                .antMatchers("/zzz/**").access("hasRole('AAA') and hasAnyRole('MASTER', 'ZZZ')")
                // 注意:这行会覆盖后续的anyRequest配置,建议根据实际需求调整或移除
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
        .and()
        // 后续配置...
}

注意:.antMatchers("/**").permitAll()会匹配所有请求,导致.anyRequest().authenticated()完全失效,建议根据实际开放路径调整这行配置。

二、使用Lambda表达式/自定义授权管理器(适用于Spring Security 5.7+)

5.7版本后官方弃用了WebSecurityConfigurerAdapter,同时access方法不再接受字符串参数,推荐用Lambda表达式或自定义AuthorizationManager实现逻辑:

方式1:直接用Lambda表达式

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .headers().frameOptions().disable()
        .and()
            .authorizeHttpRequests(auth -> auth
                .antMatchers("/aaa/**", "/bbb/**").permitAll()
                .antMatchers("/ccc", "/ddd/**").hasRole("AAA")
                .antMatchers("/zzz/**").access((authentication, context) -> {
                    Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
                    // Spring Security的hasRole会自动添加ROLE_前缀,判断时需对应
                    boolean hasAAA = authorities.stream().anyMatch(a -> a.getAuthority().equals("ROLE_AAA"));
                    boolean hasMasterOrZzz = authorities.stream().anyMatch(a -> 
                        a.getAuthority().equals("ROLE_MASTER") || a.getAuthority().equals("ROLE_ZZZ")
                    );
                    return hasAAA && hasMasterOrZzz ? AuthorizationDecision.authorized() : AuthorizationDecision.denied();
                })
                .anyRequest().authenticated()
            )
        .and()
        // 后续配置...
}

方式2:封装自定义AuthorizationManager(复用性更强)

// 封装可复用的授权逻辑
private AuthorizationManager<RequestAuthorizationContext> requireAAAAndEitherMasterOrZzz() {
    return (authentication, context) -> {
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        boolean hasAAA = authorities.stream().anyMatch(a -> a.getAuthority().equals("ROLE_AAA"));
        boolean hasMasterOrZzz = authorities.stream().anyMatch(a -> 
            a.getAuthority().equals("ROLE_MASTER") || a.getAuthority().equals("ROLE_ZZZ")
        );
        return new AuthorizationDecision(hasAAA && hasMasterOrZzz);
    };
}

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .headers().frameOptions().disable()
        .and()
            .authorizeHttpRequests(auth -> auth
                .antMatchers("/aaa/**", "/bbb/**").permitAll()
                .antMatchers("/ccc", "/ddd/**").hasRole("AAA")
                .antMatchers("/zzz/**").access(requireAAAAndEitherMasterOrZzz())
                .anyRequest().authenticated()
            )
        .and()
        // 后续配置...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:35:21