Spring Security资源服务器SpEL访问Bean报EL1057E无Bean解析器错误
问题根因
抛出EL1057E: No bean resolver registered in the context to resolve access to bean 'ipWhitelistingProvider'的核心原因是:Spring Security Web请求授权链路中使用的SpEL表达式求值上下文,没有挂载可以关联Spring容器的Bean解析器。
默认情况下Spring Security资源服务器的表达式求值上下文是独立隔离的,仅支持框架内置的SpEL变量(比如#oauth2.hasScope()这类OAuth2内置表达式),不支持@自定义Bean名.方法()这种直接引用Spring容器中Bean的语法。即使在配置类中手动注入了对应的自定义Bean,也无法打通SpEL的Bean解析链路——因为SpEL求值的上下文和配置类的依赖注入是完全隔离的,一旦SpEL解析器碰到@开头的Bean引用,找不到对应解析器就会抛出该错误。
解决方案
不需要修改自定义Bean的代码,只需要在资源服务器的安全配置中,给授权链路注入支持Bean解析的表达式处理器,同时保留原有的OAuth2内置表达式能力:
- 在
ResourceServerConfiguration配置类中注入Spring应用上下文:@Autowired private ApplicationContext applicationContext; - 定义自定义的OAuth2授权表达式处理器,保留原有内置能力的同时补上Bean解析逻辑:
@Bean public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler() { OAuth2WebSecurityExpressionHandler handler = new OAuth2WebSecurityExpressionHandler(); // 注入应用上下文后,处理器会自动生成关联Spring容器的BeanResolver,支持@开头的Bean引用 handler.setApplicationContext(applicationContext); return handler; } - 在HttpSecurity的授权配置中显式指定使用上面定义的表达式处理器,替换默认的无Bean解析能力的处理器:
@Override public void configure(HttpSecurity http) throws Exception { http .authorizeRequests() // 关键:指定自定义的表达式处理器 .expressionHandler(oAuth2WebSecurityExpressionHandler()) .antMatchers("/").permitAll() .antMatchers("/config/**").access("@ipWhitelistingProvider.isItValid(request) or #oauth2.hasScope('config')") .anyRequest().authenticated() .and().csrf().disable(); }
常见踩坑提醒
- 不要错误替换为
DefaultWebSecurityExpressionHandler:如果用这个类做自定义处理器,会丢失OAuth2内置的#oauth2相关表达式能力,导致#oauth2.hasScope('config')这类语法抛出变量找不到的错误。 - 多Security配置场景下要保证配置优先级:如果项目中存在多个继承
WebSecurityConfigurerAdapter的安全配置类,需要给当前资源服务器配置加上@Order注解,保证该配置的优先级覆盖其他通用安全配置,避免自定义的表达式处理器不生效。 - 不需要手动编写自定义BeanResolver实现类:只要给
OAuth2WebSecurityExpressionHandler注入ApplicationContext,框架内部会自动在初始化阶段创建ApplicationContextBeanResolver,不需要重复造轮子。 - 不推荐通过自定义SpEL变量的方式传递Bean:比如手动把
ipWhitelistingProvider塞进求值上下文的变量映射里,这种方式会增加冗余代码,通过框架原生的BeanResolver能力支持@语法是符合设计规范的实现,可维护性更强。
内容的提问来源于stack exchange,提问作者Jayant Kokitkar
相关产品推荐
相关产品推荐

