0. Servlet Filter VS. HandlerInterceptor
아래 그림에서와 같이 Filter는 DispatcherSevlet 앞에서 먼저 동작한다.
Interceptor는 Dispatcher Servlet에서 Controller(Handler)사이에서 동작한다.
1) 필터
- 웹 어플리케이션의 Context 역할
- 스프링 기능을 활용하기 어려움
- 일반적으로 인코딩, CORS, XSS, LOG, 인증, 권한 등을 구현
2) 인터셉터
- 스프링의 Spring Context의 기능이며 일종의 빈
- 스프링 컨테이너여서 다른 빈을 주입하여 활용성이 좋다.
- 다른빈을 활용할 수 있어 보통 인증, 권한 등 구현함
1. JwtFilter에서 OncePerRequestFilter 상속 VS GenericFilterBean 또는GenericFilterBean상속받은 AbstractAuthenticationProcessingFilter차이
1) OncePerRequestFilter : 요청 당 단 한번의 실행을 보장한다. 아래의 그림과 같이 4) 다시 first, second filter를 타지 않고
first, second filter는 한 번만 탄다. 예를 들어 인증처리를 할 경우 아래와 같이 두 번 first, second filter를 타면 불필요한 처리를 반복하게 된다.
public class JwtFilter extends OncePerRequestFilter {
private static final Logger logger = LogManager.getLogger(JwtFilter.class);
public static final String AUTHORIZATION_HEADER = "Authorization";
private TokenProvider tokenProvider;
public JwtFilter(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
// 포함하지 않을 url
private static final List<String> EXCLUDE_URL =
Collections.unmodifiableList(
Arrays.asList(
"/static/**",
"/favicon.ico",
"/admin",
"/api/signIn",
"/api/signUp",
"/admin/signIn",
"/admin/signUp"
));
// jwt의 인증정보를 현재 실행중인 SecurityContext에 저장하는 역할 수행
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String jwt = resolveToken(request);
String requestURI = request.getRequestURI();
// Request Header에서 jwt를 꺼내오고 그 jwt가 유효하면
if(StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
Authentication authentication = tokenProvider.getAuthentication(jwt);
// securityContext에 저장한다.
SecurityContextHolder.getContext().setAuthentication(authentication);
logger.debug("Security Context에 '{}' 인증 정보를 저장했습니다, uri: {}", authentication.getName(), requestURI);
} else {
logger.debug("유효한 JWT 토큰이 없습니다, uri: {} ", requestURI);
}
filterChain.doFilter(request, response);
}
//Request Header에서 토큰 정보를 꺼내오기 위한 resolverToken 메소드
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
if(StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request){
return EXCLUDE_URL.stream().anyMatch(exclude -> exclude.equalsIgnoreCase(request.getServletPath()));
}
}
2. SpringSecurity에서의 FilterChain과 Servlet의 Filter
https://velog.io/@seongwon97/Spring-Security-Filter%EB%9E%80
SecurityFilterChain
https://velog.io/@kose/SecurityFilterChain-%EB%8B%A4%EC%A4%91-%ED%95%84%ED%84%B0-%EA%B4%80%EB%A6%AC
'Back-end > Spring-핵심& webMVC' 카테고리의 다른 글
Rate Limiting Mechanism (0) | 2023.08.31 |
---|---|
gradle, maven 차이 및 빌드에 관하여 (0) | 2023.02.12 |
@RequestBody, @RequestPart (0) | 2023.01.15 |
Lombok @Setter 사용 지양 & lombok.config (0) | 2023.01.07 |
Spring 예외 처리 전략 및 Global 예외처리 // @RestControllerAdivce (0) | 2023.01.03 |