- 현재 URL만 알면 로그인 안한 사용자도 어디든 접근이 가능하다.
- 이때, 각각의 로직마다 로그인 여부를 체크하면 되지만,
필터와 인터셉터를 사용하면 이 기능을 편리하게 사용할 수 있다.- 필터
- 서블릿이 제공해주는 기능
- 인터셉터
- 스프링이 제공해주는 기능
- 각각의 장단점이 존재하므로 상황에 맞게 사용해야한다.
- 필터
필터
필터흐름 : HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러\ 필터제한 : HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러 //로그인 사용자 HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단, 서블릿 호출X) //비 로그인 사용자 필터체인 : HTTP 요청 -> WAS -> 필터1(예시:로그) -> 필터2(예시:로그인 여부) -> 필터3 -> 서블릿 -> 컨트롤러 |
필터를 적용하면 필터가 호출 된 다음에 서블릿이 호출된다.
참고로 필터는 특정 URL 패턴에 적용할 수 있다. /* 이라고 하면 모든 요청에 필터가 적용된다.
.스프링을 사용하는 경우 여기서 말하는 서블릿은 스프링의 디스패처 서블릿으로 생각하면 된다.
- 사용
- Filter 인터페이스를 상속 받은 후 구현하면 된다. (javax.servlet)
- init() - 필드 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출
- doFilter() - 고객의 요청이 올때마다 해당메서드가 호출, 필터의 로직 구현 부분
HTTP 라면 request를 HttpServletRequest로 다운캐스팅 - destroy() - 필터 종료 메서드, 서블리 ㅅ컨테이너가 종료될 때 호출
- chain.doFilter(request, response)를 반드시 호출하자! (호출하지 않으면 다음단계로 진행되지 않는다)
해당 메서드를 호출해야 다음(필터||서블릿)을 호출한다.
- Filter 인터페이스를 상속 받은 후 구현하면 된다. (javax.servlet)
- 실무에서 HTTP 요청시 같은 요청의 로그에 모두 같은 식별자를 자동으로 남기는 방법은 logback mdc로 검색
해보자.
빈 등록
@ServletComponentScan @WebFilter(filterName = "logFilter", urlPatterns = "/*")
필터 등록이 가능하지만 필터 순서 조절이 안된다. 따라서 FilterRegistrationBean 을 사용하자.
//수동 빈 등록
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = newFilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter()); //등록할 필터지정
filterRegistrationBean.setOrder(1); //순번(낮을수록 먼저)
filterRegistrationBean.addUrlPatterns("/*"); //필터동작 URI지정
return filterRegistrationBean;
}
인터셉터
인터셉터 흐름: HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러 인터셉터 제한: HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러 //로그인 사용자 HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터(적절하지 않은 요청이라 판단, 컨트롤러 호출X) // 비 로그인 사용자 인터셉터 체인: HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 인터셉터1 -> 인터셉터2 -> 컨트롤러 ``` 스프링 인터셉터는 체인으로 구성되는데, 중간에 인터셉터를 자유롭게 추가할 수 있다. |
- 제공 메서드
- preHandle : 컨트롤러 호출 전에 실행 (핸들러 어댑터 실행 전 실행)
- preHandle의 리턴값의 boolean, 응답값이 true 이면 다음으로 진행하고, false 이면 더는 진행하지 않는다.
- postHandle : 컨트롤러 호출 후에 실행 (핸들러 어댑터 실행 후 실행)
- 컨트롤러에서 예외가 발생하면 실행되지 않는다.
- afterCompletion: 뷰 렌더링 된 이후에 실행된다.
- 컨트롤러에서 예외가 발생해도 실행된다.
- preHandle : 컨트롤러 호출 전에 실행 (핸들러 어댑터 실행 전 실행)
인터셉터는 스프링 MVC 구조에 특화된 필터 기능을 제공한다고 이해하면 된다. 스프링 MVC를 사용하고, 특별히 필터
를 꼭 사용해야 하는 상황이 아니라면 인터셉터를 사용하는 것이 더 편리하다.
- 인터셉터 빈 등록법
- Configuration클래스에 WebMvConfigurer 인터페이스를 상속받는다.
- addInterceptors메서드를 오버라이딩 하고, 매개변수에서 생성되는 InterceptorRegistry 클래스의
addInterceptors(인터셉터 설정파일 생성) ex: new LogInterceptor()
.order() //실행 순번
.addPathPatterns() //인터셉터를 적용할 URL
.excludePathPatterns() //인터셉터 적용하지 않을 URL
? 한 문자 일치 * 경로(/) 안에서 0개 이상의 문자 일치 ** 경로 끝까지 0개 이상의 경로(/) 일치 {spring} 경로(/)와 일치하고 spring이라는 변수로 캡처 {spring:[a-z]+} matches the regexp [a-z]+ as a path variable named "spring" {spring:[a-z]+} regexp [a-z]+ 와 일치하고, "spring" 경로 변수로 캡처 {*spring} 경로가 끝날 때 까지 0개 이상의 경로(/)와 일치하고 spring이라는 변수로 캡처 /pages/t?st.html — matches /pages/test.html, /pages/tXst.html but not /pages/ toast.html /resources/*.png — matches all .png files in the resources directory /resources/** — matches all files underneath the /resources/ path, including / resources/image.png and /resources/css/spring.css /resources/{*path} — matches all files underneath the /resources/ path and captures their relative path in a variable named "path"; /resources/image.png will match with "path" → "/image.png", and /resources/css/spring.css will match with "path" → "/css/spring.css" /resources/{filename:\\w+}.dat will match /resources/spring.dat and assign the value "spring" to the filename variable 링크: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/pattern/PathPattern.html |
'Spring' 카테고리의 다른 글
[Spring] Exception (예외) - 기본 http 요청 에러처리 (0) | 2024.05.28 |
---|---|
[Spring] ArgumentResolver (0) | 2024.05.25 |
[Spring] 쿠키, 세션 (0) | 2024.05.21 |
[Spring] Bean Validation (0) | 2024.05.16 |
[Spring] 검증(Validation) (1) | 2024.05.15 |