Spring Security 6.x基于表达式的访问控制失效问题求助
核心问题分析
错误栈中的关键提示 EL1057E: No bean resolver registered in the context to resolve access to bean 'webSecurity' 说明:WebExpressionAuthorizationManager 默认没有配置Spring容器的Bean解析器,导致SpEL表达式无法识别并调用容器中的webSecurity Bean,最终触发403授权失败。
解决方案
方案一:为WebExpressionAuthorizationManager配置Bean解析器
通过手动注入ApplicationContext,给WebExpressionAuthorizationManager设置带Bean解析能力的表达式处理器:
@Configuration @EnableWebSecurity public class SecurityConfig { private final ApplicationContext applicationContext; // 注入Spring上下文 public SecurityConfig(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // 创建带Bean解析能力的表达式处理器 DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler(); expressionHandler.setApplicationContext(applicationContext); // 初始化授权管理器并绑定处理器 WebExpressionAuthorizationManager authorizationManager = new WebExpressionAuthorizationManager("@webSecurity.check(authentication,request)"); authorizationManager.setExpressionHandler(expressionHandler); return http .authorizeHttpRequests(authorize -> authorize.requestMatchers("/test/**") .access(authorizationManager) ) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and().csrf().disable() .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) .build(); } }
方案二:改用类型安全的AuthorizationManager(推荐Spring Security 6+)
Spring Security 6+更推荐使用类型安全的AuthorizationManager替代SpEL表达式,避免Bean解析问题:
- 修改
WebSecurity实现AuthorizationManager接口:
@Component public class WebSecurityAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> { @Override public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) { Authentication auth = authentication.get(); HttpServletRequest request = context.getRequest(); // 原check方法的授权逻辑 return new AuthorizationDecision(true); } }
- 在SecurityConfig中注入并使用该授权管理器:
@Configuration @EnableWebSecurity public class SecurityConfig { private final WebSecurityAuthorizationManager webSecurityAuthorizationManager; public SecurityConfig(WebSecurityAuthorizationManager webSecurityAuthorizationManager) { this.webSecurityAuthorizationManager = webSecurityAuthorizationManager; } @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(authorize -> authorize.requestMatchers("/test/**") .access(webSecurityAuthorizationManager) ) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and().csrf().disable() .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) .build(); } }
方案对比
- 方案一适合需要保留SpEL表达式写法的场景,通过补全Bean解析能力解决问题;
- 方案二更符合Spring Security最新的设计理念,类型安全、易于调试维护,避免SpEL语法和Bean解析相关的潜在问题。
内容的提问来源于stack exchange,提问作者Assaduzzaman Assad
相关产品推荐
相关产品推荐

