본문 바로가기

Spring Security

Spring Security @EnableWebSecurity(debug = true) 오류 해결

배경

@Configuration
@EnableWebSecurity
class AuthConfig(
) {

// ...securityFilterChain 메서드 등
}

 

스프링 시큐리티를 사용하면 위와 같은 스프링 시큐리티 설정 클래스를 만들어야 한다.

 

여기서 @Configuration은 이 클래스를 Spring의 설정 클래스로 만드는 어노테이션이다.

 

@EnableWebSecurity는 Spring Security를 사용하도록 활성화하는 어노테이션이다. 이 어노테이션이 있는 클레스는 Spring Security를 구성하고 필터 체인을 정의할 수 있다.

 

@EnableWebSecurity debug라는 optional element를 가지고 있다. 이 속성은 Spring Security에서 디버깅 지원을 제어한다. 기본값은 ‘false’이다.

디버깅 모드가 활성화되면 Spring Security는 보다 자세한 로그를 출력해 문제 해결에 도움을 준다. 주의할 점은, 실제 운영 환경에서는 디버깅 모드를 비활성해야 한다는 것이다. 보안에 민감한 정보가 로깅될 수 있기 때문이다.

실제 디버깅 모드를 활성화하고 애플리케이션을 실행하면 콘솔에 이런 경고문구가 찍힌다.

********************************************************************
**********        Security debugging is enabled.       *************
**********    This may include sensitive information.  *************
**********      Do not use in a production system!     *************
********************************************************************

 


문제 발생

디버그 모드를 실행하는 방법은 @EnableWebSecurity(debug = true)로 설정하는 것이다.

프로젝트 애플리케이션에서 스프링 시큐리티 디버그 모드를 활성화하기 위해서 해당 옵션을 설정하고 서버를 실행시켰다. 이때 어마어마한 양의 오류 메시지를 콘솔에서 마주하며 서버가 실행되지 않았다.

 

여기서 키워드가 될 만한 것들을 간단하게 나열하자면 다음과 같다.

  • org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'applicationTaskExecutor': Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
  • org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain'
  • Error creating bean with name 'springSecurityFilterChain'
  • Caused by: org.springframework.beans.BeanInstantiationException
  • Caused by: java.lang.IllegalStateException: Couldn't find FilterChainProxy

 


문제 해결

콘솔 메시지를 차근차근 봤을 때 뭔가 개발자의 실수는 아닐 것 같다는 생각이 들었다. 그 이유는 에러 메시지에 개발자(내)가 만든 특정 클래스에 문제가 생긴 게 아니라 springSecurityFilterChain, applicationTaskExecutor 등 스프링 시큐리티에서 제공하는 클래스의 빈을 만드는 데 실패했다는 내용이었기 때문이다.

하지만 내가 설정한 시큐리티 클래스, 스프링 빈들끼리의 의존성 문제일 수도 있다는 가능성을 열어두고서 콘솔에 나온 메시지를 서치했다.

"Error creating bean with name 'applicationTaskExecutor'"

 

검색 결과 문제를 해결할 수 없을 것 같아서 다른 검색어로 구글링을 해보았다.

spring security enable web security debug = true docs

 

 

공식 문서를 참고하려고 검색하였는데, 결과적으로 여기서 나온 3번째 결과(https://github.com/spring-projects/spring-security/issues/14458)를 보고 문제점이 뭔지 알게 되었다.

 

나와 증상이 똑같았고, #14370의 중복이라 하여서 (https://github.com/spring-projects/spring-security/issues/14370) 이슈를 확인해보았다.

 

코멘트를 읽어보면 이미 해결된 이슈였는데, 6.3.0, 6.2.2, 6.1.7에 적용되었다.
(https://github.com/spring-projects/spring-security/commit/7cd626fe2569346b945feec40fa16f231a558fde)

 

프로젝트는 스프링 시큐리티 “6.2.1” 버전을 사용하고 있었다.

→ 버전을 6.2.2로 고치면 되겠구나!

 

build.gradle의 dependencies에 spring security 의존성을 모두 6.2.2로 고친 뒤, Gradle Reload를 하였다.

→ 이제 되겠지?

 

그러나 서버를 실행했을 때 동일한 오류가 발생했다.

프로젝트의 External Libraries를 확인해보니 6.2.1버전이 여전히 남아있음을 확인할 수 있었다.

 

 

아무래도 6.2.1이 남아있는 것 때문에 안 되는 것처럼 보였다.

버전을 명시했음에도 왜 6.2.1이 의존성으로 남아있는 건지 그 원인을 찾아보다가, 깃허브 이슈에 적힌 코멘트에서 힌트를 얻었다.
https://github.com/spring-projects/spring-security/issues/14642

 

FilterChainProxy issue with Spring Boot 3.2.2 · Issue #14642 · spring-projects/spring-security

Describe the bug We are updating our Spring Boot 3.1.5 project to 3.2.2 And we are getting this issue with FilterChainProxy: org.springframework.beans.factory.BeanCreationException: Error creating ...

github.com

 

https://github.com/spring-projects/spring-security/issues/14370

 

Application context fails to load: Couldn't find FilterChainProxy · Issue #14370 · spring-projects/spring-security

Describe the bug Application context fails to load after upgrading from spring boot version 3.1.5 to 3.2.1 with error message: “Couldn't find FilterChainProxy” in a list of Filters. SecurityConfig ...

github.com

 

 

내용을 읽어보면 스프링 부트 3.2.2는 스프링 시큐리티 6.2.1을 사용한다는 내용이다.

 

그리고 우리 프로젝트는 스프링부트 3.2.2를 쓰고 있었다. 코멘트의 내용처럼 스프링 부트의 업그레이드가 필요했다.

 

스프링 부트의 어떤 버전에서 어떤 의존성을 사용하는지는 이곳에서 찾으면 된다.

https://github.com/spring-projects/spring-boot/releases

 

다만 스프링 부트가 꼭 이곳에 적힌 의존성 버전만 사용하도록 강요하는 건 아닌 것 같은데, 버전을 명시했음에도 그 버전으로 덮어씌워지지 않고(변경되지 않고) 두 버전이 다 남아있는 것은 의문이다.

 

다른 프로젝트를 만들어 실험해 보았을 때, 스프링부트 3.2.2로 설정하고 스프링 시큐리티를 6.2.2 버전으로 명시해서 의존성을 추가했을 때 이 프로젝트와는 다르게 6.2.2 버전만 의존성에 추가되어있는 것을 확인했다. 이때는 당연히 시큐리티 debug 모드도 정상적으로 실행된다.

 

테스트로 만든 프로젝트와는 다르게 이 프로젝트는 멀티 모듈 프로젝트이고, 모듈 간 의존성이 복잡하게 설정되어 있는데 이쪽에 원인이 있는것이 아닌가 짐작만 될 뿐이다.

 

스프링 부트 버전을 “3.2.3”으로 변경한 뒤 의존성에 스프링 시큐리티 6.2.1이 없어짐을 확인하였고, 디버깅 모드도 정상적으로 실행되었다.

알게된 것

1, 스프링 부트버전과 라이브러리 버전의 호환성 문제 때문에 예전에도 오랫동안 삽질하고 고생을 겪은 적이 있는데, 이해가 되지 않는 에러에 한번씩 호환성을 체크하는 습관을 가져야겠다.

2. 콘솔, 공식문서, 공식 리포지토리를 꼼꼼하게 읽자.