스프링 시큐리티를 공부하면서 필터, 인터셉터에 대해 더 자세한 공부를 하게 됐다.
클라이언트에서 요청이 있을 경우
Filter -> InterCeptor -> AOP -> InterCeptor -> FIlte이다.
1. 서버를 실행시켜 서블릿이 올라오는 동안 init() 실행, 그 후 doFilter() 실행
2. Controller에 들어가기 전 preHandler 실행
3. Controller에서 나와 postHandler, after Completion, doFilter 순으로 진행
4. 서블릿 종료 시 destory가 실행
Filter
- 필터는 요청과 응답을 한번 필터링 해주는 역할
- 필터는 스프링 컨텍스트 외부에 존재
- 인코딩 변환처리, xss방어 들의 요청에 대한 처리로 사용된다.
- 필터의 실행 메소드
1. init(): 필터 인스턴스 초기화
- init 메소드는 필터 객체를 초기화하고 서비스에 추가하기 위한 메소드
- 웹 컨테이너가 1회 init 메소드를 호출하여 필터 객체를 초기화하면 이후의 요청들은 doFilter를 통해 처리
2. doFilter(): 전, 후 처리
- doFilter 메소드는 url-pattern에 맞는 모든 HTTP 요청이 디스패처 서블릿으로 전달되기 전에 웹 컨테이너에 의해 실행되는 메소드
- doFilter의 파라미터로는 FilterChain이 있는데, FilterChain의 doFilter 통해 다음 대상으로 요청을 전달
- chain.doFilter() 전/후에 우리가 필요한 처리 과정을 넣어줌으로써 원하는 처리를 진행
3. destory(): 필터 인스턴스 종료
- destroy 메소드는 필터 객체를 서비스에서 제거하고 사용하는 자원을 반환하기 위한 메소드
- destroy 메소드는 웹 컨테이너에 의해 1번 호출되며 이후에는 이제 doFilter에 의해 처리되지 않는다.
Interceptor
- 요청에 대한 작업 전/후로 사전 작업해주는 역할
- 인터셉터는 스프링의 DispatcherServlet이 Controller를 호출하기 전, 후에 동작
- 여러개 사용 가능
- 로그인 확인, 권한 확인, 프로그램 실행 시간 계산 작업 로그확인 등의 업무 처리로 사용된다.
- 인터셉터의 실행 메소드
1. preHandler(): Controller 메소드가 실행 되기 전
- preHandle 메소드는 Controller가 호출되기 전에 실행
- Controller 이전에 처리해야 하는 전처리 작업이나 요청 정보를 가공하거나 추가하는 경우에 사용
- preHandle의 3번째 파라미터인 handler 파라미터는 핸들러 매핑이 찾아준 Controller 빈에 매핑되는 HandlerMethod라는 새로운 타입의 객체로써, @RequestMapping이 붙은 메소드의 정보를 추상화한 객체이다.
- preHandle의 반환 타입은 boolean인데 반환값이 true이면 다음 단계로 진행이 되지만, false라면 작업을 중단하여 이후의 작업(다음 인터셉터 또는 컨트롤러)은 진행되지 않는다.
2. postHandler(): Controller 메소드 실행 직 후 view 렌더링 전
- postHandle 메소드는 컨트롤러를 호출된 후에 실행
- Controller 이후에 처리해야 하는 후처리 작업이 있을 때 사용
- postHandle 메소드에는 컨트롤러가 반환하는 ModelAndView 타입의 정보가 제공되는데, 최근에는 Json 형태로 데이터를 제공하는 RestAPI 기반의 Controller(@RestController)를 만들면서 자주 사용되지는 않는다.
3. afterCompletion(): view 렌더링 후
- afterCompletion 메소드는 이름 그대로 모든 뷰에서 최종 결과를 생성하는 일을 포함해 모든 작업이 완료된 후에 실행
- 요청 처리 중에 사용한 리소스를 반환할 때 사용하기에 적합함
필터(Filter) vs 인터셉터(Interceptor) 차이 및 용도
- 필터와 인터셉터는 각각이 관리되는 컨테이너와 Request/Response의 조작가능 여부가 다르고, 그에 따라 용도가 다르다.
- Request/Response 객체 조작 가능 여부
public SampleFilter implements Filter {
public void doFilter(ServletRequest request
, ServletResponse response
, FilterChain chain) {
// 필터가 다음 필터를 호출하기 위해서는 필터 체이닝(다음 필터 호출)을 해주어야 한다.
chain.doFilter(request, response);
}
}
- 필터는 Request와 Response를 조작할 수 있지만 인터셉터는 조작할 수 없다.
public class SampleInterceptor implements HandlerInterceptor {
default boolean preHandle(HttpServletRequest request
, HttpServletResponse response
, Object handler) {
// Request/Response를 교체할 수 없고 boolean 값만 반환할 수 있다.
return true;
}
}
- 디스패처 서블릿이 여러 인터셉터 목록을 가지고 있고, for문으로 순차적으로 실행
- true를 반환하면 다음 인터셉터가 실행되거나 컨트롤러로 요청이 전달되며, false가 반환되면 요청이 중단
- 필터(Filter)의 용도 및 예시
1. 공통된 보안 및 인증/인가 관련 작업
2. 모든 요청에 대한 로깅 또는 감사
3. 이미지/데이터 압축 및 문자열 인코딩
4. Spring과 분리되어야 하는 기능
- 인터셉터(Interceptor)의 용도 및 예시
1. 세부적인 보안 및 인증/인가 공통 작업
2. API 호출에 대한 로깅 또는 감사
3. Controller로 넘겨주는 정보(데이터)의 가공
출처
'개발 > Java & Kotlin' 카테고리의 다른 글
[JPA] 기본 영속성 관리 - 내부 동작 방식 (0) | 2022.07.11 |
---|---|
[Java] 재귀 알고리즘 (0) | 2022.07.11 |
[Java] 스택과 큐 (0) | 2022.07.10 |
[Java] 검색 (0) | 2022.07.10 |
[Java] 기본 자료구조 (0) | 2022.07.08 |