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

SpringBoot2.7 OAuth2资源服务器AuthenticationEventPublisher失效

问题背景

此前基于Spring Boot 2.6编写OAuth2资源服务器安全配置时,通过继承WebSecurityConfigurerAdapter实现JWT校验逻辑,运行正常,原配置代码如下:

@Configuration @EnableWebSecurity
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                . . . 
            .and()
                .oauth2ResourceServer()
                    .jwt();
    }
}

升级至Spring Boot 2.7后,按照官方推荐方案,使用标注@Bean、返回SecurityFilterChain的方法替代已废弃的WebSecurityConfigurerAdapter进行配置,发现应用中AuthenticationEventPublisher不再正常工作,升级后的配置代码如下:

@Configuration @EnableWebSecurity
public class ResourceServerConfig {

    @Bean
    public SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                . . . 
            .and()
                .oauth2ResourceServer()
                    .jwt();
        return http.build();
    }
}
问题排查

问题根源已经定位:BearerTokenAuthenticationFilter始终采用ProviderManager作为AuthenticationManager实现,而ProviderManager默认将eventPublisher属性初始化为NullEventPublisher,这个空实现不会发布任何认证事件,相关源码片段如下:

public class ProviderManager implements AuthenticationManager, . . . {

    . . .

    private AuthenticationEventPublisher eventPublisher = new NullEventPublisher();

在原先使用WebSecurityConfigurerAdapter的场景下,框架会自动为ProviderManager注入DefaultAuthenticationEventPublisher的有效实例,因此认证事件可正常发布。

临时方案与顾虑

测试找到的临时修复方案分两步:

  1. 编写全局配置类生成自定义ProviderManager Bean,注入JwtAuthenticationProvider并为其设置Spring容器中存在的AuthenticationEventPublisher实例,配置代码如下:
@Configuration
@ConditionalOnClass({AuthenticationEventPublisher.class, JwtAuthenticationProvider.class})
public class SpringConfiguration { //global configuration for several others
    @Bean
    public ProviderManager providerManagerAvecDefaultAuthenticationPublisher(@Lazy JwtDecoder jwtDecoder, AuthenticationEventPublisher authenticationPublisher) {
        JwtAuthenticationProvider authenticationProvider = new JwtAuthenticationProvider(jwtDecoder);
        ProviderManager providerManager = new ProviderManager(Arrays.asList(authenticationProvider));
        providerManager.setAuthenticationEventPublisher(authenticationPublisher);
        return providerManager;
    }
}
  1. 在各应用的安全配置中注入该ProviderManager,通过oauth2ResourceServer().jwt().authenticationManager(manager)方法显式指定认证管理器,即可恢复事件发布能力,调整后的安全配置如下:
@Configuration @EnableWebSecurity
public class ResourceServerConfig {

    @Autowired ProviderManager manager; //1

    @Bean
    public SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                . . . 
            .and()
                .oauth2ResourceServer()
                    .jwt()
                    .authenticationManager(manager); //2
        return http.build();
    }
}

这个方案存在两个明显问题:

  • 开发的模块是供公司内部数十个应用依赖的通用组件,用于统一发布特定日志,该方案要求所有接入应用都手动添加注入ProviderManager、显式配置认证管理器的代码,接入改造成本过高。
  • 无法确认强制为所有接入应用预置自定义ProviderManager会带来哪些潜在兼容性风险。
咨询问题

是否存在可行方案,能够绕过ProviderManager默认初始化NullEventPublisher的逻辑,无需所有配置SecurityFilterChain的应用都手动调用oauth2ResourceServer().authenticationManager(manager)指定认证管理器,即可让AuthenticationEventPublisher正常发布认证事件?

解决方案

直接在通用组件里注册一个BeanPostProcessor,在Spring容器初始化BearerTokenAuthenticationFilter实例完成后,取出它内部持有的ProviderManager,把容器里的AuthenticationEventPublisher设置进去即可。全程不需要业务应用做任何代码改动,也不会替换全局默认的ProviderManager实例,没有额外兼容性风险。
实现代码如下:

@Bean
public BeanPostProcessor bearerTokenFilterEventPublisherConfigurer(AuthenticationEventPublisher eventPublisher) {
    return new BeanPostProcessor() {
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof BearerTokenAuthenticationFilter filter) {
                AuthenticationManager authManager = filter.getAuthenticationManager();
                if (authManager instanceof ProviderManager providerManager) {
                    providerManager.setAuthenticationEventPublisher(eventPublisher);
                }
            }
            return bean;
        }
    };
}

这个方案的优势很明确:

  • 不修改框架原有创建ProviderManager、BearerTokenAuthenticationFilter的流程,完全复用Spring Security默认的自动配置逻辑,不会和其他自定义安全配置产生冲突。
  • 只针对资源服务器用到的BearerTokenAuthenticationFilter持有的认证管理器做事件发布器注入,影响范围可控,不会干扰其他认证链路(比如表单登录、短信登录等场景用到的独立ProviderManager实例)。
  • 配置放在通用组件里,业务应用引入依赖后自动生效,零接入成本。

如果需要覆盖所有Spring Security自动创建的ProviderManager实例(不只是OAuth2资源服务器场景),直接把判断逻辑改成匹配ProviderManager类型即可,同样不需要业务侧做任何改动。


内容的提问来源于stack exchange,提问作者André Campanini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:09:20