WebSecurityConfigurerAdapter如何配置无@PreAuthorize方法访问规则
配置方案
不需要自定义AccessDecisionManager,直接调整两层安全校验的规则即可,按以下两步修改:
- 第一步:开启方法级注解支持
在你的WebSecurityConfigurerAdapter实现类上添加注解,开启@PreAuthorize注解的解析能力:
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) // 核心注解,必须添加 public class SecurityConfig extends WebSecurityConfigurerAdapter { // 其余配置保留 }
- 第二步:修改HttpSecurity拦截规则
把原有配置里的anyRequest().authenticated()替换为permitAll(),关闭过滤器层面的全局限制:
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() // 静态资源、登录接口等特殊规则可按原有逻辑写在前面,匹配优先级从上到下 // .antMatchers("/static/**", "/auth/login").permitAll() .anyRequest().permitAll() .and() // 原有其他配置比如formLogin、csrf、cors规则全部保留即可 .csrf().disable(); }
实现原理
Spring Security的权限校验是两层独立执行的逻辑:
- 第一层是Servlet过滤器链上的URL规则校验,也就是
configure(HttpSecurity)中配置的内容,执行时机在请求进入Controller之前。配置anyRequest().permitAll()后,这一层不会对任何请求做认证、权限拦截,所有请求都能顺利到达Controller匹配环节。 - 第二层是AOP实现的方法级校验,只要开启了
prePostEnabled = true,Spring会在Controller方法实际调用前拦截请求,检查方法上的@PreAuthorize注解:- 如果方法标注了@PreAuthorize,就按注解内的SpEL表达式做校验,比如
hasAuthority('SOME_ROLE')会校验用户权限,isAuthenticated()会校验用户登录状态,校验不通过直接返回403或跳转登录页 - 如果方法没有标注任何方法级安全注解,这层校验直接跳过,方法正常执行,正好实现「未标注@PreAuthorize的方法默认放行所有请求」的效果
- 如果方法标注了@PreAuthorize,就按注解内的SpEL表达式做校验,比如
自定义AccessDecisionManager不生效的原因
全局AccessDecisionManager是服务于第一层过滤器链URL校验的,它执行时Spring还没完成请求到Controller方法的匹配,根本拿不到当前请求对应方法上的注解元数据,自然没法实现「有注解就校验、无注解就放行」的逻辑,强行在这里写判断反而会绕开方法级校验,和需求相悖。
注意事项
配置完成后,所有需要做登录校验、角色权限校验的方法,必须显式添加@PreAuthorize注解——哪怕只是要求登录不需要特殊角色,也要标注@PreAuthorize("isAuthenticated()"),否则会因为默认放行导致未登录用户可访问。如果担心漏加,可以写简单的单元测试,扫描所有Controller的public方法,对没有标注@PreAuthorize、@PermitAll等安全注解的方法做告警,避免权限泄露。
内容的提问来源于stack exchange,提问作者Auryn
相关产品推荐
相关产品推荐

