Spring Security报错:无法访问javax.servlet.Filter,类文件未找到
我在开发一个带基础认证与授权的Spring Boot项目,使用Spring Security,配置类继承了已废弃的WebSecurityConfigurerAdapter(后续计划移除)。
配置类代码:
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("spring_user") .password("password123") .roles("ADMIN"); } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()); return http.build(); } @Bean public static PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
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>3.0.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.codelib</groupId> <artifactId>basic-auth-security</artifactId> <version>0.0.1-SNAPSHOT</version> <name>basic-auth-security</name> <description>basic-auth-security</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>5.7.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
已引入spring-boot-starter-web依赖,项目其余部分无特殊内容。运行应用时出现报错:
java: cannot access javax.servlet.Filter class file for javax.servlet.Filter not found
IDEA指向配置文件,但无代码红线标注,请问该问题的原因是什么?
核心原因
版本不兼容导致依赖冲突
Spring Boot 3.0.1基于Jakarta EE 9,使用jakarta.servlet包;而手动引入的spring-security-config:5.7.3属于Spring Security 5.x版本,依赖旧的javax.servlet包,两者无法兼容,因此找不到javax.servlet.Filter类。手动引入依赖破坏Spring Boot依赖管理
spring-boot-starter-security已包含spring-security-config组件,且会自动匹配与Spring Boot版本对应的Spring Security版本(Spring Boot 3.0.1对应Spring Security 6.0.x),手动指定旧版本会覆盖默认配置,引发依赖不一致。
解决步骤
1. 移除冲突依赖
从pom.xml中删除以下手动引入的spring-security-config依赖:
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>5.7.3</version> </dependency>
2. 修复内存认证密码编码问题
原配置直接明文设置密码,未使用密码编码器,运行时会触发错误,修改configure方法:
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("spring_user") .password(passwordEncoder().encode("password123")) .roles("ADMIN"); }
3. (可选)移除废弃的WebSecurityConfigurerAdapter
既然计划移除该类,改用Spring Security 6.x推荐方式配置内存认证,删除继承关系和configure方法,新增UserDetailsService Bean:
@Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()); return http.build(); } @Bean public static PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public UserDetailsService userDetailsService() { UserDetails user = User.withUsername("spring_user") .password(passwordEncoder().encode("password123")) .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(user); } }
内容的提问来源于stack exchange,提问作者Serhii Chernikov

