Spring/Error
[Jwt]Error creating bean with name 'springSecurityFilterChain' defined in class path resource
haenni
2024. 8. 21. 20:08
😱 에러
스프링부트 시큐리티 & JWT 강의를 수강하며 시큐리티를 설정하다 Error creating bean with name 'springSecurityFilterChain' defined in class path resource라는 에러가 발생하였다.🥺
에러를 해결하고 왜 이러한 에러가 발생했는지 알아보자


error
📌 Error 파악
✏️ Error creating bean with name 'springSecurityFilterChain' defined in class path resource
: 우선 에러를 파악해보자
Error creating bean with name 'springSecurityFilterChain' defined in class path resource
[org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Failed to instantiate
[javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception with message:
class org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter cannot be cast to class javax.servlet.Filter
(org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter and javax.servlet.Filter are in unnamed module of loader 'app')
error
Error creating bean with name 'springSecurityFilterChain' defined in class path resource
찾아보니 이 오류는 javax.servlet.Filter org.springframework.security.web.context.request.async.
WebAsyncManagerIntegrationFilter 간의 클래스 캐스팅 문제로 발생하는 것 같았다.
주로 이 오류는 Spring Security와 Servlet API 간의 버전 불일치 때문에 발생하기때문에, Spring Security의 최신 버전과 Servlet API의 호환성 문제가 원인일 수 있다.
📌 오류 해결
✏️ Spring Security 버전 통일
: Spring Boot와 Security의 버전을 통일해야한다.


강사님과 똑같이 dependency를 설정하였는데, 강의가 워낙 오래되어서 그런지 나의 Spring boot 버전과 Security의 버전이 충돌이 발생한 것 같다. spring-security-config의 버전이 5.5.3으로 설정되어있었는데, Spring Boot 3.x 버전에서는 Spring Security 6.x를 사용해야한다고 한다.
또, sevlet-api는 Spring Boot의 스타터가 이미 서블릿 API를 제공하므로 javax.servlet-api을 제거해주었다.
나는 Spring Boot 3.3.2 버전을 사용중이여서 security-config dependency의 버전을 6.3.2로 변경해주었다.
security-config dependency
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>6.3.2</version>
</dependency>
Spring Security 6.0 버전 이후에는 API가 몇 가지 변경되어, Security Config도 변경해주었다.

public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable) // CSRF 보호 비활성화
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/user/**").authenticated() // "/user/**" 패턴은 인증된 사용자만 접근 가능
.requestMatchers("/admin/**").hasAnyRole("MANAGER", "ADMIN") // "/admin/**" 패턴은 MANAGER 또는 ADMIN 역할을 가진 사용자만 접근 가능
.anyRequest().permitAll() // 그 외의 요청은 모두 허용
);
http.formLogin(form -> form
.loginPage("/login") // 로그인 페이지 경로 설정
.permitAll() // 로그인 페이지는 모두 접근 가능
);
return http.build();
}
}
변경된 부분
CSRF 비활성화 설정
- 이전 버전: http.csrf(csrf -> csrf.disable())
- 새 버전: http.csrf(AbstractHttpConfigurer::disable)
- 설명: 이전 버전에서는 csrf.disable() 메서드를 사용하여 CSRF 보호를 비활성화.
Spring Security 6.x에서는 AbstractHttpConfigurer::disable을 사용하는 새로운 방식으로 CSRF 비활성화를 설정
요청 권한 설정
- 이전 버전: .authorizeRequests(authorize -> authorize .antMatchers("/user/**").authenticated() .antMatchers("/admin/**").hasAnyRole("MANAGER", "ADMIN") .anyRequest().permitAll())
- 새 버전: .authorizeHttpRequests(authorize -> authorize .requestMatchers("/user/**").authenticated() .requestMatchers("/admin/**").hasAnyRole("MANAGER", "ADMIN") .anyRequest().permitAll())
- 설명: authorizeRequests 대신 authorizeHttpRequests를 사용하여 요청 권한을 설정
antMatchers 대신 requestMatchers를 사용
