서블릿 필터 - 소개
- 로그인 체크를 하지 않으면 어떤 일이 생길까?
- 로그인을 하지 않았는데도 회원 관리가 가능하거나 상품 관리가 가능하거나 큰 문제가 생길 것이다.
- 각 컨트롤러 메소드에서 일일이 로그인 체크 로직을 넣어준다면 로그인 여부를 알 수 있긴 할 것이다.
- 다만 번거롭기도 번거롭지만, 향후 로그인 관련 로직이 변경되면 모든 로직을 다 수정해줘야 한다.
- 이를 위해 스프링에서는 서블릿 필터, 스프링 인터셉터, AOP를 제공한다.
서블릿 필터는 무슨 역할을 할까?
- 필터는 기본적으로 서블릿이 지원하는 수문장 역할을 한다.
필터의 특성
- 필터 흐름
HTTP 요청 => WAS => 필터 => 서블릿 => 컨트롤러
- 필터를 적용하면 필터가 호출 된 다음에 서블릿이 호출된다.
- 그래서 모든 고객의 요청 로그를 남기는 요구사항이 있다면 필터를 사용하면 된다.
- 참고로 필터는 특정 URL 패턴에 적용할 수 있다.
/*
이라고 하면 모든 요청에 필터가 적용된다.- 참고로 스프링을 사용하는 경우 여기서 말하는 서블릿은 스프링의 디스패처 서블릿으로 생각하면 된다.
- 필터 제한
- (로그인 사용자) HTTP 요청 => WAS => 필터 => 서블릿 => 컨트롤러
- (비 로그인 사용자) HTTP 요청 => WAS => 필터 (적절하지 않은 요청이라 판단, 서블릿 호출X)
- 필터에서 적절하지 않은 요청이라고 판단하면 거기에서 끝을 낼 수도 있다. (로그인 여부 체크에 효과적이다.)
- 필터 체인
HTTP 요청 => WAS => 필터1 => 필터2 => 필터3 => 서블릿 => 컨트롤러
- 필터는 체인으로 구성되는데, 중간에 필터를 자유롭게 추가할 수 있다.
- 예를 들어서 로그를 남기는 필터를 먼저 적용하고, 그 다음에 로그인 여부를 체크하는 필터를 만들 수 있다.
- 필터 인터페이스
- 필터 인터페이스를 구현하고 등록하면 서블릿 컨테이너가 필터를 싱글톤 객체로 생성하고, 관리한다.
init()
- 필터 초기화 메서드
- 서블릿 컨테이너가 생성될 때 호출된다.
doFilter()
- 고객의 요청이 올 때 마다 해당 메서드가 호출된다.
- 필터의 로직을 구현하면 된다.
destroy()
- 필터 종료 메서드
- 서블릿 컨테이너가 종료될 때 호출된다.
서블릿 필터 - 요청 로그
- 모든 요청을 로그로 남기는 필터를 만들고 적용해보자.
필터 만들기
필터 적용하기
@ServletComponentScan @WebFilter(filterName = "logFilter", urlPatterns = "/*")
로도 필터 등록이 가능하긴 하다.- 다만 필터 순서 조절이 안 되니 그냥 FilterRegistrationBean을 사용하자.
서블릿 필터 - 인증 체크
- 로그인 여부를 확인하는 필터를 만들고 적용해보자.
필터 만들기
필터 적용하기
RedirectURL 처리
- 로그인에 성공하면 처음 요청인 URL로 이동하는 기능을 개발해보자.
- 그저 컨트롤러에 파라미터 하나만 추가하면 된다.
@RequestParam(defaultValue = "/") String redirectUrl
- 그리고 로그인이 성공하면 해당 주소로 리다이렉트 시키기만 하면 된다.
서블릿 필터 - 객체 변환
- 서블릿 필터에는 스프링 인터셉터는 제공하지 않는 객체 변환 기능이 있다.
chain.doFilter(request, response);
를 호출해서 다음 필터 또는 서블릿을 호출할 때 request
와 response
를 다른 객체로 바꿀 수 있다.ServletRequest
와 ServletResponse
를 구현한 다른 객체를 만들어서 넘기면 해당 객체가 다음 필터 또는 서블릿에서 사용된다.- 잘 사용하는 기능은 아니라서 그냥 이런 것도 있다라고 이해하면 된다.
스프링 인터셉터 - 소개
- 서블릿 필터처럼 공통되는 부분을 처리하는 것을 동일하지만, 적용되는 순서와 범위, 사용방법이 다르다.
인터셉터의 특성
- 스프링 인터셉터 흐름
HTTP 요청 => WAS => 필터 => 서블릿 => 스프링 인터셉터 => 컨트롤러
- 스프링 인터셉터는 디스패처 서블릿과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출 된다.
- 스프링 인터셉터는 스프링 MVC가 제공하는 기능이기 때문에 결국 디스패처 서블릿 이후에 등장하게 된다.
- 스프링 MVC의 시작점이 디스패처 서블릿이라고 생각해보면 이해가 될 것이다.
- 스프링 인터셉터에도 URL 패턴을 적용할 수 있는데, 서블릿 URL 패턴과는 다르고, 매우 정밀하게 설정할 수 있다.
- 스프링 인터셉터 제한
(로그인 사용자) HTTP 요청 => WAS => 필터 => 서블릿 => 스프링 인터셉터 => 컨트롤러
(비 로그인 사용자) HTTP 요청 => WAS => 필터 => 서블릿 => 스프링 인터셉터(적절하지 않은 요청이라 판단, 컨트롤러 호출 X)
- 인터셉터에서 적절하지 않은 요청이라고 판단하면 거기에서 끝을 낼 수도 있다. 그래서 로그인 여부를 체크하기에 딱 좋다.
- 스프링 인터셉터 체인
HTTP 요청 => WAS => 필터 => 서블릿 => 인터셉터1 => 인터셉터2 => 컨트롤러
- 스프링 인터셉터는 체인으로 구성되는데, 중간에 인터셉터를 자유롭게 추가할 수 있다.
- 예를 들어서 로그를 남기는 인터셉터를 먼저 적용하고, 그 다음에 로그인 여부를 체크하는 인터셉터를 만들 수 있다.
- 스프링 인터셉터 인터페이스
- 스프링의 인터셉터를 사용하려면
HandlerInterceptor
인터페이스를 구현하면 된다. - preHandle
- 컨트롤러 호출 전에 호출된다. (더 정확히는 핸들러 어댑터 호출 전에 호출된다.)
- preHandle의 응답값이 true면 다음으로 진행하고, false 이면 더는 진행하지 않는다.
- false인경우 나머지 인터셉터는 물론이고, 핸들러 어댑터도 호출되지 않는다.
- postHandle
- 컨트롤러 호출 후에 호출된다. (더 정확히는 핸들러 어댑터 호출 후에 호출된다.)
- afterCompletion
- 뷰가 렌더링 된 이후에 호출된다.
- 예외가 발생한 경우에도 항상 호출된다.
스프링 인터셉터 - 요청 로그
인터셉터 만들기
인터셉터 적용하기
- WebConfig에 추가해주자.
- WebMvcConfigurer 인터페이스를 구현해줘야 한다.
스프링 인터셉터 - 인증 체크
- 이번에는 로그인 여부를 확인하는 인터셉터를 만들어보자.
인터셉터 만들기
인터셉터 적용하기
- WebConfig의 addInterceptors에 추가해주자.
ArgumentResolver 활용
- 이번에는 ArgumentResolver를 통해서 로그인한 회원을 조금 편리하게 찾는 방법을 알아보자.
- 전용 애노테이션을 생성해서 리졸버를 통해 해당 애노테이션이 존재하면 로그인한 회원 정보를 반환하는 방법이다.
애노테이션 생성
리졸버 만들기
리졸버 적용하기
출처