Reactive应用配置SecurityWebFilterChain报错:authenticationManager cannot be null
问题详情
在反应式Spring Boot应用中实现SecurityWebFilterChain后,启动抛出以下异常:核心错误为java.lang.IllegalArgumentException: authenticationManager cannot be null,外层包裹org.springframework.beans.factory.UnsatisfiedDependencyException。移除spring-boot-starter-oauth2-resource-server依赖后应用可正常启动,但该依赖是实现自定义authenticationManager的必需项。未修改WebSecurityConfiguration类时应用启动正常,怀疑与依赖版本或自动配置冲突有关。
错误堆栈
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration': Unsatisfied dependency expressed through method 'setSecurityWebFilterChains' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [com/test123/test123/security/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.server.SecurityWebFilterChain]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalArgumentException: authenticationManager cannot be null at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:768) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:720) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.24.jar:5.3.24] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.24.jar:5.3.24] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.24.jar:5.3.24] at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[spring-boot-2.7.7.jar:2.7.7] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.7.jar:2.7.7] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.7.jar:2.7.7] at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.7.jar:2.7.7] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.7.jar:2.7.7] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.7.jar:2.7.7] at com.test123.test123.Test123Application.main(Test123Application.java:12) ~[classes/:na] Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [com/test123/test123/security/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.server.SecurityWebFilterChain]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalArgumentException: authenticationManager cannot be null
Web安全配置类
@Configuration @EnableWebFluxSecurity @EnableReactiveMethodSecurity public class WebSecurityConfiguration { @Bean public SecurityWebFilterChain springSecurityFilterChain( ServerHttpSecurity http) { http.csrf().disable() .authorizeExchange() .pathMatchers("/test").permitAll() // .and().formLogin().authenticationFailureHandler((exchage, exception) -> Mono.error(exception)) .and().httpBasic(); // .and().oauth2ResourceServer().authenticationManagerResolver(customAuthenticationManager()); return http.build(); } }
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.7</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.test123</groupId> <artifactId>test123</artifactId> <version>0.0.1-SNAPSHOT</version> <name>test123</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> <spring.cloud-version>2021.0.5</spring.cloud-version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.nimbusds</groupId> <artifactId>oauth2-oidc-sdk</artifactId> <version>6.5</version> </dependency> <dependency> <groupId>com.nimbusds</groupId> <artifactId>nimbus-jose-jwt</artifactId> <version>8.21</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud-version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
解决方案
问题根源
引入spring-boot-starter-oauth2-resource-server后,Spring Security自动配置逻辑会尝试初始化OAuth2资源服务器相关组件,即使你注释掉了配置代码,自动配置依然会触发。此时如果没有提供有效的AuthenticationManager或相关配置(如JWT解码器),就会抛出authenticationManager cannot be null异常。
修复方案
1. 显式配置ReactiveAuthenticationManager
如果需要保留HTTP Basic认证并使用自定义认证逻辑,显式注册ReactiveAuthenticationManagerBean,并在配置中指定:
@Configuration @EnableWebFluxSecurity @EnableReactiveMethodSecurity public class WebSecurityConfiguration { // 基于用户信息仓库的默认认证管理器,可替换为自定义实现 @Bean public ReactiveAuthenticationManager reactiveAuthenticationManager(UserDetailsRepository userDetailsRepository) { UserDetailsRepositoryReactiveAuthenticationManager authManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsRepository); // 可添加密码编码器等配置 // authManager.setPasswordEncoder(passwordEncoder()); return authManager; } @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, ReactiveAuthenticationManager authenticationManager) { http.csrf().disable() .authorizeExchange() .pathMatchers("/test").permitAll() .anyExchange().authenticated() .and().httpBasic().authenticationManager(authenticationManager); // 若需启用OAuth2资源服务器,补充配置示例: // .and().oauth2ResourceServer().jwt().jwtDecoder(jwtDecoder()); return http.build(); } }
2. 排除OAuth2资源服务器自动配置
如果暂时不需要OAuth2资源服务器的自动配置,可在启动类中排除相关配置类,避免冲突:
@SpringBootApplication(exclude = {OAuth2ResourceServerAutoConfiguration.class}) public class Test123Application { public static void main(String[] args) { SpringApplication.run(Test123Application.class, args); } }
3. 修复依赖版本冲突
手动指定的com.nimbusds依赖版本可能与Spring Boot依赖管理中的版本冲突,建议移除手动版本号,使用Spring Boot提供的兼容版本:
<!-- 移除以下手动指定版本的依赖,由Spring Boot自动管理 --> <!-- <dependency> <groupId>com.nimbusds</groupId> <artifactId>oauth2-oidc-sdk</artifactId> <version>6.5</version> </dependency> <dependency> <groupId>com.nimbusds</groupId> <artifactId>nimbus-jose-jwt</artifactId> <version>8.21</version> </dependency> -->
关键提示
- 当引入
spring-boot-starter-oauth2-resource-server时,Spring Security会自动创建OAuth2ResourceServerWebFilter,该组件必须依赖有效的认证组件(如JwtDecoder或AuthenticationManager)。 - 若同时使用HTTP Basic和OAuth2资源服务器,需确保两者的认证管理器配置互不冲突。
内容的提问来源于stack exchange,提问作者Adek

