728x90
반응형
서블릿 필터
- 필터는 서블릿이 지원하는 필터이다.
- 서블릿을 호출하기 전 필터를 사용하여 전처리를 할 수 있다.
- 필터는 서블릿의 영역이다.
필터의 동작 방식
필터 흐름
- 필터의 기본적인 흐름
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러
필터 제한
- 필터에 제한을 두어 서블릿을 호출 하지 않게 할 수 있다.
HTTP 요청 -> WAS -> 필터 (적절하지 않을 경우 여기서 중단)
필터 체인
- 필터를 여러개 중복해서 사용할 수 있다.
HTTP 요청 ->WAS-> 필터1-> 필터2-> 필터3-> 서블릿 -> 컨트롤러
필터의 인터 페이스의 메소드
init(): 필터 초기화 메서드
public default void init(FilterConfig filterConfig) throws ServletException
doFilter(): 고객의 요청이 올 때 마다 해당 메서드가 호출된다.
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
destroy(): 필터 종료메서드, 서블릿 컨테이너가 종료될때 호출 된다.
public default void destroy() {}
필터의 구현 과정
- 필터 인터페이스 구현
- WebConfig(@Configuration이 붙은 클래스) 에 필터 등록
로그 필터 구현
- doFilter: 요청이 올때 해당 메소드 가 호출 된다.
- chain.doFilter(request, response);
- 다음 필터가 있으면 필터를 호출하고 없으면 서블릿을 호출 한다.
@Slf4j
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("log filter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("log filter doFilter");
// 다운 캐스팅 필요 기능이 별로 없기 때문에
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String requestURI = httpServletRequest.getRequestURI();
String uuid = UUID.randomUUID().toString();
try {
log.info("REQUEST [{}][{}]", uuid, requestURI);
// doFitler 를 안하면 서블릿으로 넘어가지 않는다.
chain.doFilter(request, response);
} catch (Exception e) {
throw e;
} finally {
log.info("RESPONSE");
}
}
@Override
public void destroy() {
log.info("log filter destroy");
}
}
필터 설정
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
//필터 등록
filterFilterRegistrationBean.setFilter(new LogFilter());
// 필터 우선순위 설정
filterFilterRegistrationBean.setOrder(1);
// 필터를 적용할 요청 URL
filterFilterRegistrationBean.addUrlPatterns("/*");
filterFilterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);
return filterFilterRegistrationBean;
}
}
로그인 체크 필터 구현
- 필터를 상속받아 구현을 한다.
- 동일하게 webconfig 에 등록을 해주면 된다.
public class LoginCheckFilter implements Filter {
private static final String[] whiteList = {"/", "/login", "/members/add", "/logout", "/css/*"};
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
HttpServletResponse httpResponse = (HttpServletResponse)response;
try {
log.info("인증 체크 필터 시작 {}", requestURI);
if (isLoginCheckPath(requestURI)) {
log.info("인증 케트 로직 실행", requestURI);
HttpSession session = httpRequest.getSession(false);
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
log.info("미인증 사용자임", requestURI);
// 로그인 페이지로 보내버린뒤 다시 조회할 페이지를 넣어준다.
httpResponse.sendRedirect("/login?redirectURL=" + requestURI);
return;
}
}
chain.doFilter(request,response);
} catch (Exception e) {
throw e; // 예외 로깅 가능 하지만, 톰캣 까지 예외를 보내줘야 함.
} finally {
log.info("인증 체크 필터 종료 {}", requestURI);
}
}
/**
* 화이트 리스트의 경우 인증 체크 X
*/
private boolean isLoginCheckPath(String requestURI) {
return !PatternMatchUtils.simpleMatch(whiteList, requestURI);
}
중요부분
- 필터안에서 리턴을 해버리면 다음단계 즉 서블릿을 호출 단계 까지 가진 않는다.
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
log.info("미인증 사용자임", requestURI);
// 로그인 페이지로 보내버린뒤 다시 조회할 페이지를 넣어준다.
httpResponse.sendRedirect("/login?redirectURL=" + requestURI);
return; // 필터안에서 그냥 리턴을 할 경우 다음으로 진행되지 않는다.
}
참고:
728x90
반응형
'Spring > spring mvc 2 스터디' 카테고리의 다른 글
[Spring] Filter Vs Interceptor (0) | 2022.06.01 |
---|---|
[Spring] Interceptor (0) | 2022.06.01 |
[Spring] 로그인 처리 세션 (0) | 2022.05.25 |
[Spring] 로그인 처리 쿠키 (0) | 2022.04.16 |
[Spring] Validation: Validator (0) | 2022.02.02 |
댓글