Spring Security์์ ๋ฐ์ํ ์์ธ๊ฐ ControllerAdvice์์ ํธ๋ค๋ง๋๋ ๋ฌธ์
์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ์ํ Exception์ด ControllerAdvice์ ํธ๋ค๋ง๋๋ ๊ฒ์ด ๋ญ๊ฐ ๋ฌธ์ ์ผ๊น์?
์ต๊ทผ์ Client์๊ฒ ์ ๋ฌํ๋ error ๋ฉ์ธ์ง๋ฅผ ๊ณตํตํํ๊ธฐ ์ํด Rest Controller Advice์ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ฝ๋๋ฅผ ์ถ๊ฐํ์์ต๋๋ค.
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
...
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(HttpServletRequest request, Exception exception)
return ResponseEntity.internalServerError()
.body(ErrorResponse.badRequest(exception.getMessage(), request.getRequestURI()));
}
}
์์์น ๋ชปํ ์์ธ ๋ฐ์์ผ๋ก ํด๋น Exception๊ณผ ์ผ์นํ๋ ์๊ทธ๋์ฒ๋ก ์ ์๋ ๋ฉ์๋๊ฐ ์์ ๊ฒฝ์ฐ, ๊ณตํต์ ์ผ๋ก ํธ์ถ๋๊ฒ๋ ๋ฉ์๋์ ๋๋ค.
๋ชฉํํ๋ error ๋ฉ์ธ์ง๋ ๊ณตํตํ ํ ์ ์์์ง๋ง ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์์ต๋๋ค. Security์์ ๋ฐ์ํ๋ ์ธ์ฆ, ์ธ๊ฐ ์ค๋ฅ๊ฐ ํด๋น ๋ฉ์๋์ ์บ์น๋์ด 500 ์๋ฌ๋ฅผ ์ ๋ฌํ ๋ค๋ ๊ฒ์ ๋๋ค.
๋ชจ๋๊ฐ ์์๋ค์ํผ ์ธ์ฆ์ ์คํจํ์ ๊ฒฝ์ฐ์๋ 401 ์๋ฌ์ฝ๋๋ฅผ, ์ธ๊ฐ์ ์คํจํ์ ๋๋ 403 ์๋ฌ์ฝ๋๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค.
Spring Security๋ Filter ๋จ์์ ๋์ํ๊ธฐ ๋๋ฌธ์ ์์ธ๊ฐ ๋ฐ์ํ๋๋ผ๋ Spring Context ๋ด๋ถ์ ์๋ ControllerAdvice๊น์ง ์ ํ๋์ง ์๋๋ค๊ณ ์๊ฐํ๋๋ฐ ์ด์งธ์ ํด๋น ๋ฉ์๋์ ์บ์น๋์ด ์ด๋ฌํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฑธ๊น์?
Spring Security์ ๋์ ์์น
๐ก ํด๋น ๊ฒ์๋ฌผ์์๋ Spring Security์ ๊ดํ ์์ธํ ๋์์๋ฆฌ๋ฅผ ์ค๋ช ํ๊ณ ์์ง ์์ต๋๋ค! ๐ โ๏ธ
์๋ Spring Security Architecture ์ด๋ฏธ์ง์ ๋๋ค. ์๋ฒ๋ก ๋ค์ด์จ Http Request๊ฐ Controller์ ๋๋ฌํ๊ธฐ ์ AuthenticationFilter๊ฐ ํด๋น ์์ฒญ์ ๊ฐ๋ก์ฑ ์ธ์ฆ ๋ก์ง์ ์ํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผSecurityContextHolder์ ์ ์ฅํฉ๋๋ค.
๊ทธ ํ ์์ฒญ์ด ์ปจํธ๋กค๋ฌ์ ๋๋ฌํ๊ธฐ ์ SecurityInterceptor๊ฐ ์คํ๋์ด ๋ณด์ ๊ท์น์ ๋ฐ๋ผ ์์ฒญ์ ๊ฒ์ฌํ๊ณ ์ฌ์ฉ์์ ๊ถํ์ ํ์ธํฉ๋๋ค. ์ธ๊ฐ ๋ก์ง์ ์ํํ๋ ๊ฑฐ์ฃ .
๊ทธ๋ ๋ค๋ฉด ์ธ์ฆ, ์ธ๊ฐ ๋ชจ๋ Controller ๋ฐ์์ ์คํ๋๋๋ฐ ์ด๋ป๊ฒ ControllerAdvice์ ์บ์น๊ฐ ๋ ๊ฑธ๊น์?
๊ทธ ์ด์ ๋ SecurityInterceptor ๊ตฌํ์ฒด์ ์์ต๋๋ค.
SecurityInterceptor์ ๊ตฌํ์ฒด๋ FilterSecurityInterceptor ์ MethodSecurityInterceptor๋ก ๋๋๋๋ฐ, FilterSecurityInterceptor๋ Servlet ํํฐ์ ํํ๋ก ๋์ํ์ง๋ง MethodSecurityInterceptor๋ Spring์ AOP๋ฅผ ์ฌ์ฉํ์ฌ ์คํ๋ง ์ดํ๋ฆฌ์ผ์ด์ ์์์ ๋์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
- FilterSecurityInterceptor
- HTTP ์์ฒญ์ ๋ํ ์ ๊ทผ ์ ์ด๋ฅผ ์ํด ์ฌ์ฉ
- ๋ณดํต Spring Security์ ๋ณด์ ํํฐ ์ฒด์ธ์์ ์ฌ์ฉ๋ฉ๋๋ค.
- URL ํจํด๊ณผ ๊ถํ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์์ ์์ฒญ์ ์ธํฐ์ ํธํ๊ณ ์ ๊ทผ์ ํ์ฉํ๊ฑฐ๋ ๊ฑฐ๋ถํฉ๋๋ค. antMatchers() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ URL ํจํด๊ณผ ๊ถํ์ ์ง์ ํ ์ ์์ต๋๋ค. ์ด ์ธํฐ์ ํฐ๋ ๋ณดํต Spring Security์ XML ๋๋ Java Config๋ฅผ ํตํด ์ค์ ๋ฉ๋๋ค.
- MethodSecurityInterceptor
- ๋ฉ์๋ ํธ์ถ์ ๋ํ ์ ๊ทผ ์ ์ด๋ฅผ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
- ์ฃผ๋ก ๋ฉ์๋ ์์ค์ ๋ณด์์ ์ฒ๋ฆฌํฉ๋๋ค.
- @PreAuthorize, @PostAuthorize, @Secured ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ๋ฉ์๋ ์์ค์ ๋ณด์์ ์ค์ ํฉ๋๋ค.
์ฆ, ์ฐ๋ฆฌ๊ฐ ํํ ์ฌ์ฉํ๋ ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ ๊ถํ ์ ์ธ์ Filter๊ฐ ์๋ Spring ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ์ฒ๋ฆฌ๋๊ฒ ๋๋ ๊ฒ์ ๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
๋ค์ ๋ฌธ์ ๋ก ๋์์ Spring Security Exception์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋ฉด ๋ ๊น์?
ControllerAdvice์์ ์บ์น๊ฐ ๋๋ค๋ฉด ๋ค๋ฅธ ์์ธ๋ค๊ณผ ๋์ผํ๊ฒ Exception๊ณผ ์๊ทธ๋์ฒ๊ฐ ๋์ผํ ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ฉด ๋๊ฒ ๋ค ์๊ฐํ ์ ์์ง๋ง Spring Context ๋ด์์ ๋ฐ์ํ Exception(AccessDeniedException)์ ์๋ ์ด๋ฏธ์ง์ ๊ฐ์ด ExceptionTranslationFilter์ ์ํด์ ์ธ์ฆ ์์ธ(AuthenticationException)์ ์ธ๊ฐ ์์ธ(AccessDeniedException)๋ก ๋ถ๊ธฐ๋๊ธฐ ๋๋ฌธ์ Filter๋ฅผ ํ๊ธฐ์ ์ Exception์ ์ฒ๋ฆฌํ ๊ฒฝ์ฐ ์ํ๋ ์๋ฌ ์ํ์ฝ๋์ ๋ฐ์ง ๋ชป ํ ์ ์์ต๋๋ค.
์ ๊ฐ ํด๊ฒฐํ ๋ฐฉ๋ฒ์ ํด๋น Exception์ด ๊ธฐ์กด ๋ก์ง๋๋ก Filter์์ ๋ถ๊ธฐ๋ ์ ์๋๋ก ๋์ง๋ ๊ฒ(throw)์ ๋๋ค.
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<ErrorResponse> handleException(AccessDeniedException exception) {
throw exception;
}
spring-projects Github์ ๋์ผํ ์ด์๋ฅผ ์ฐพ์๋๋ฐ ๋ง์ฐฌ๊ฐ์ง๋ก rethrowํ๊ธฐ๋ฅผ ๊ถ์ฅํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
https://github.com/spring-projects/spring-security/issues/6908
AccessDeniedHandler and AuthenticationEntryPoint does not work Because of the global exception handler · Issue #6908 · spring-
Summary AccessDeniedHandler and AuthenticationEntryPoint do not work because the global exception handler is defined Actual Behavior When the request has an AuthenticationException or an AccessDeni...
github.com
๋ง๋ฌด๋ฆฌ
๋๋ฌด ํ๋ฌดํ ๊ฒฐ๋ก ์ผ๊น์?ใ ใ
์์ธ๋ฅผ ๊ทธ๋ฅ ๋์ ธ์ผํ๋๊ฒ ์ฐ์ฐํ ์๋ ์์ง๋ง Security์ ๊ธฐ๋ณธ ๋ก์ง์ ์ํํ ๋ค์ custom filter๋ฅผ ๋ฑ๋กํ์ฌ ์๋ต ๋ฉ์ธ์ง๋ฅผ ๊ณตํตํํ๋๊ฒ ์ข๊ฒ ๋ค๋ ๊ฒฐ๋ก ์ ๋ด๋ ธ์ต๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋จ์ ํ์ง๋ง Spring Security๊ฐ Filter์์๋ง ๋์ํ๋๊ฒ ์๋๋ผ๋ ๊ฒ์ ์๊ฒ๋์์ต๋๋ค.
๋ ์ข์ ํด๊ฒฐ๋ฐฉ๋ฒ์ ์๊ณ ๊ณ์๊ฑฐ๋ ์๋ชป๋ ๋ด์ฉ์ด ์๋ค๋ฉด ๋๊ธ ๋จ๊ฒจ์ฃผ์ธ์. ๋๊น์ง ๋ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค :)
Spring MVC ํจํด๊ณผ Filter์ ๋ํ ์ค๋ช
์ด ๊ถ๊ธํ๋ค๋ฉด ์๋ ๊ฒ์๊ธ์ ์ฐธ๊ณ ํด์ฃผ์ธ์.
[Spring] Spring MVC : https://clipcode.tistory.com/62
[Spring] Filter์ Interceptor ์ฐจ์ด : https://clipcode.tistory.com/65
Reference.
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] OpenFeign์ ์ด์ฉํ์ฌ API ํต์ ํด๋ณด๊ธฐ (feat. ๊ณ ์์ด ์ฌ์ง ๊ฒ์) (2) | 2023.04.25 |
---|---|
[Spring] Filter์ Interceptor ์ฐจ์ด (2) | 2023.04.22 |
[JPA] ์ปค์ ๊ธฐ๋ฐ pagenation ๊ตฌํํ๊ธฐ (8) | 2023.03.01 |
[JPA] ์คํ์ ๊ธฐ๋ฐ Pagenation ๊ตฌํํ๊ธฐ (0) | 2023.03.01 |
[Spring] Spring MVC (0) | 2023.02.18 |
๋๊ธ