필터의 흐름
HTTP 요청 > WAS > 필터 > 서블릿(디스패처 서블릿) > 컨트롤러
필터제한
HTTP 요청 > WAS > 필터 > 서블릿 > 컨트롤러 // 로그인 사용자일 경우
HTTP 요청 > WAS > 필터( 적절하지 않은 요청이라 판단, 서블릿 호출 X) // 비 로그인 사용자일 경우
필터체인
HTTP 요청 > WAS > 필터1 > 필터2 > 필터3 > 서블릿 > 컨트롤러
public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
public default void destroy() {}
}
@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 httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
String uuid = UUID.randomUUID().toString();
try{
log.info("REQUEST [{}{}]", uuid, requestURI);
// 다음필터를 호출한다.
chain.doFilter(request,response);
}catch (Exception e){
throw e;
}finally {
log.info("RESPONSE [{}{}]", uuid, requestURI);
}
}
@Override
public void destroy() {
log.info("log filter destroy");
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new LogFilter()); // 만든 필터 넣어주고
filterFilterRegistrationBean.setOrder(1); // 필터 우선순위 정해주고
filterFilterRegistrationBean.addUrlPatterns("/*"); // 모든 경로에 다 적용한다.
return filterFilterRegistrationBean;
}
}
logback mdc도 한번 검색해보자.
@Slf4j
public class LoginFilter implements Filter {
// 들어올수 있는 경로
private static final String[] whiteList = {"/", "/members/add", "/login", "/logout", "/css/*"};
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String requestURI = httpServletRequest.getRequestURI();
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
try{
log.info("인증체크 필터 시작 {}",requestURI);
if(isLoginCheckPath(requestURI)) {
log.info("인증 체크 로직 실행 {}", requestURI);
HttpSession session = httpServletRequest.getSession(false);
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER)==null) {
log.info("미인증 사용자가 요청했다 !{}", requestURI);
// 로그인으로 리다이렉트
httpServletResponse.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);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
리다이렉트 부분은 컨트롤러에서 @RequestParam(defaultValue="/") String redirectURL 파라미터로 받아서 처리해줘야 한다.