Factory method 'securityFilterChain' threw exception with message: The Filter class ~~.JwtVerificationFilter does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.

ํ˜„์ฃผยท2024๋…„ 3์›” 11์ผ
0

Trouble Shooting

๋ชฉ๋ก ๋ณด๊ธฐ
28/32

๐Ÿ”ฅ ๋ฌธ์ œ

Spring Boot์˜ ๋ฒ„์ „์ด 3.x๋กœ ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ Spring Security + JWT๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•  ๋•Œ SecurityConfig๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์ด ์กฐ๊ธˆ ๋‹ฌ๋ผ์กŒ๋‹ค!

๐Ÿ“Œ Spring Boot 3.x securityConfig์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๊ฐœ๋…๋“ค์€ ์•„๋ž˜ ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

์›๋ž˜ Spring Boot 2.x ๋ฒ„์ „์—์„œ๋Š”

JwtVerificationFilter์™€ JwtAuthenticaitonFilter ๋‘๊ฐœ๋ฅผ ๋งŒ๋“ค์–ด์„œ ํ•„ํ„ฐ์— ์ถ”๊ฐ€ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด

AbstractHttpConfigurer๋ฅผ ๊ตฌํ˜„ํ•œ CustomFilterConfigurer๋ฅผ ๋งŒ๋“ค์–ด ๊ทธ ์•ˆ์—์„œ ๋‘ ํ•„ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€ ํ›„,

securityFilterChain์— http.apply(customFilterConfigurer)๋กœ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ฒ„์ „์ด ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ apply() ๋ฉ”์„œ๋“œ๋Š” deprecated๋˜์–ด์„œ ๋ชป์“ฐ๋Š” ์ƒํƒœ๊ฐ€ ๋˜์–ด ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผ ํ–ˆ๋‹ค.

๐Ÿ’ก deprecated๋œ ๋ฉ”์„œ๋“œ๋“ค ์ฐธ๊ณ 


์ค‘๊ฐ„ ๊ณผ์ •

์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ฐพ์•„๋ณด๋‹ˆ configurer์— ๋นˆ Customizer ๋ฉ”์„œ๋“œ๋ฅผ ๋„ฃ์–ด๋†“๊ณ 

.with() ๋ฉ”์„œ๋“œ๋กœ configurer, customizer ์ด๋ ‡๊ฒŒ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค๋Š” ๊ธ€์ด ์žˆ์–ด์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ํ•ด๋ณด์•˜๋‹ค.

ํ•˜์ง€๋งŒ ๋Œ์•„์˜ค๋Š” ๊ฒƒ์€ ์—๋Ÿฌ

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityFilterChain' defined in class path resource [com/jp/backend/global/config/SecurityConfig.class]: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'securityFilterChain' threw exception with message: The Filter class com.jp.backend.auth.filter.JwtVerificationFilter does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.

์—๋Ÿฌ ๋ฉ”์„ธ์ง€๋Š” ๋Œ€์ถฉ JwtVerificationFilter ํด๋ž˜์Šค์— ๋“ฑ๋ก๋œ ์ˆœ์„œ๊ฐ€ ์—†์œผ๋ฉฐ, ๋ช…์‹œ์ ์ธ ์ˆœ์„œ ์—†์ด๋Š” ํ•„ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ง€์ ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ•˜๋‚˜ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€

๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ custom DSL์„ ์ ์šฉํ•˜๋ผ๊ณ  ๋‚˜์™€์žˆ๋‹ค.

๊ธฐ๋ณธ๊ฐ’์„ ๋น„ํ™œ์„ฑํ™” ํ• ๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ํ•˜๋ผ๊ณ  ๋˜์–ด์žˆ์—ˆ๊ธฐ์—

์ผ๋‹จ ๋‚˜๋Š” customizer ๊ฐ’์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ € ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

์ด๋ ‡๊ฒŒ ํ–ˆ๋Š”๋ฐ ์ผ๋‹จ run์€ ์ž˜ ๋Œ์•„๊ฐ”๊ณ ..!! ํ•˜์ง€๋งŒ ํ•„ํ„ฐ ๋กœ๊ทธ๋ฅผ ๋ณด๋‹ˆ

์›๋ž˜๋ผ๋ฉด ์ € ๋กœ๊ทธ์•„์›ƒ ํ•„ํ„ฐ ๋’ค์—
com.jp.backend.auth.filter.JwtAuthenticationFilter@2b86e36b, com.jp.backend.auth.filter.JwtVerificationFilter@3973fe2b
๋‘ ํ•„ํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€์•ผํ•˜๋Š”๋ฐ ์•ˆ๋“ค์–ด๊ฐ”๋‹จ ๋ง์ž…๋‹ˆ๋‹ค์š”

INFO 25648 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@530e500c, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1c3b4de1, org.springframework.security.web.context.SecurityContextHolderFilter@66e6e5e9, org.springframework.security.web.header.HeaderWriterFilter@c310aa3, org.springframework.web.filter.CorsFilter@1925b113, org.springframework.security.web.authentication.logout.LogoutFilter@7abc838a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@654ab198, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6b334a1, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@eaa901a, org.springframework.security.web.session.SessionManagementFilter@5536542e, org.springframework.security.web.access.ExceptionTranslationFilter@740ddb41, org.springframework.security.web.access.intercept.AuthorizationFilter@7afffc81]

์šฐ์—์—์—์—ฅใ„ฑ
๊ทธ๋ž˜์„œ ๋˜ ์–ด์ฐŒ์ €์ฐŒ ์ฐพ์•„๋ณด๋‹ค๊ฐ€ ์ด๋ฒˆ์—๋Š” configuer ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์ง€ ์•Š๊ณ  securityFilterChain ์ฝ”๋“œ ์•ˆ์— ๊ด€๋ จ ๋‚ด์šฉ์„ ๋„ฃ์–ด์ค€ ํ›„์—

.addFilterBofore๋กœ ํ•„ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋•จ

์ด๋ ‡๊ฒŒ ํ•˜๊ณ  run์„ ํ–ˆ๋”๋‹ˆ ์ผ๋‹จ ์ž˜ ๋Œ์•„๊ฐ€๊ธฐ๋„ ํ•˜๊ณ  ํ•„ํ„ฐ๋„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž˜ ์ถ”๊ฐ€๊ฐ€ ๋œ ๋ชจ์Šต์ด๋‹ค.

Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@7abc838a, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@2ee91bdf, org.springframework.security.web.context.SecurityContextHolderFilter@7d4bb16b, org.springframework.security.web.header.HeaderWriterFilter@56a7f57f, org.springframework.web.filter.CorsFilter@1a034bbc, org.springframework.security.web.authentication.logout.LogoutFilter@2179127d, com.jp.backend.auth.filter.JwtAuthenticationFilter@5453b15d, com.jp.backend.auth.filter.JwtVerificationFilter@4a6dd88e, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@79224636, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@35307365, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2c3c05ff, org.springframework.security.web.session.SessionManagementFilter@636d4cdc, org.springframework.security.web.access.ExceptionTranslationFilter@6000ca67, org.springframework.security.web.access.intercept.AuthorizationFilter@dc72335]

ํ•˜์ง€๋งŒ ๋กœ๊ทธ์ธ์„ ํ•ด๋ณด๋‹ˆ ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋‚˜ํƒ€๋‚ฌ๋‹ค!

Cannot invoke "org.springframework.security.authentication.AuthenticationManager.authenticate(org.springframework.security.core.Authentication)" because "this.authenticationManager" is null
at com.jp.backend.auth.filter.JwtAuthenticationFilter.attemptAuthentication(JwtAuthenticationFilter.java:63) ~[main/:na]

http.getSharedObject(AuthenticationManager.class); ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ AuthenticationManager ๊ฐ€ null ๊ฐ’์œผ๋กœ ๋‚˜์™€์„œ ๋‚˜์˜ค๋Š” ์—๋Ÿฌ์˜€๋Š”๋ฐ

์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณด๊ณ  AuthenticationManager๋ฅผ @Bean์œผ๋กœ ๋“ฑ๋กํ•ด๋ด๋„ ์ž˜ ์•ˆ๋ผ์„œ

๋ฉฐ์น ๊ฐ„์˜ ์„œ์น˜ ๋์— ์•„์ด๋””์–ด๋ฅผ ์–ป์–ด์„œ ํ•ด๋ณด์•˜๋‹ค.


โ˜˜๏ธ ํ•ด๊ฒฐ

์œ„์—์„œ AuthenticationManager๊ฐ€ null๋กœ ๋“ค์–ด์˜จ๋‹ค๊ณ  ํ–ˆ์œผ๋‹ˆ๊นŒ

์•„์˜ˆ filterChain์—์„œ http.getSharedObject(AuthenticationManager.class);๋ฅผ ๋นผ๊ณ 

AuthenticationManager Bean์„ ์ƒ์„ฑํ•œ ํ›„์—

์ธ์ž๋กœ AuthenticationManager authenticationManager๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ํ•ด๊ฒฐ๋˜๋Š” ๋ฌธ์ œ์˜€๋‹ค !

์ด๋ ‡๊ฒŒ ํ•˜๊ณ  ๋Œ๋ฆฌ๋ฉด ํ•„ํ„ฐ์—๋„ ์ถ”๊ฐ€๊ฐ€ ๋˜๊ณ , ๋กœ๊ทธ์ธ์„ ํ•ด๋„ header์— AccessToken์ด ์ž˜ ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค !

0๊ฐœ์˜ ๋Œ“๊ธ€