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라는 에러가 발생하였다.🥺
에러를 해결하고 왜 이러한 에러가 발생했는지 알아보자

 

SecurityConfig.java

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의 버전을 통일해야한다.

기존의 security dependency
기존의 sevlet-api dependency

강사님과 똑같이 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도 변경해주었다.

기존의 SecurityConfig.java

 

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를 사용

 

에러 해결!