목차
Filter
Filter는 Spring Context 이전에 실행 되기 때문에 Spring자체와는 무관하며 Web Application에 등록이 된다.
요청이 DispatcherServlet에 도착하기 전에 처리를 하거나 요청이 끝나고 응답할 때 마지막으로 처리를 하는 역할을 한다.
주로 인코딩 , 요청에 대한 인증 , 권한 체크 와 같은 요청에 대한 전역적인 처리를 할 때 사용한다.
Filter 인터페이스
init
doFilter
실제 로직 처리(Filter Chain을 따라 다을 Filter로 움직인다.)
destroy
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 () {} }
Filter Chain
Filter는 Client와 Servlet사이에 존재해 Client가 보내는 요청정보를 가공해 Servlet으로 보내고 Servelt이 보내는 응답정보를 가공해 Client에게 전달하는 역할을 한다. Filter는 일반적인 경우 1개가 존재하지만 여러개의 필터를 모아 Filter Chain을 형성할 수 있다.
Login Filter 생성하기 @Slf4j public class LoginFilter implements Filter { @Override public void init (FilterConfig filterConfig) throws ServletException { log.info("log filter init" ); Filter.super .init(filterConfig); } @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, request); chain.doFilter(request, response); }catch (Exception e){ throw e; }finally { log.info("RESPONSE [{}][{}]" , uuid, requestURI); } } @Override public void destroy () { log.info("log filter destroy" ); Filter.super .destroy(); } }
Filter 등록하기 스프링 부트에서는 내장 톰캣을 가지고 있어 자바코드로 Filter를 Java Code를 이용해 손 쉽게 등록할 수 있다. FilterRegistrationBean 객체를 생성해 만드러준 Filter 를 Bean 으로 등록한다.
@Configuration public class WebConfig { @Bean public FilterRegistrationBean logFilter () { FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean <Filter>(); filterRegistrationBean.setFilter(new LoginFilter ()); filterRegistrationBean.setOrder(1 ); filterRegistrationBean.addUrlPatterns("/*" ); return filterRegistrationBean; } }
@Slf4j public class LoginCheckFilter implements Filter { private static final String[] whitelist = {"/" , "/members/add" , "/login" , "/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); } } private boolean isLoginCheckPath (String requestURI) { return !PatternMatchUtils.simpleMatch(whitelist, requestURI); } }
@Configuration public class WebConfig { @Bean public FilterRegistrationBean logFilter () { FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean <>(); filterRegistrationBean.setFilter(new LoginFilter ()); filterRegistrationBean.setOrder(1 ); filterRegistrationBean.addUrlPatterns("/*" ); return filterRegistrationBean; } @Bean public FilterRegistrationBean logCheckFilter () { FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean <>(); filterRegistrationBean.setFilter(new LoginCheckFilter ()); filterRegistrationBean.setOrder(2 ); filterRegistrationBean.addUrlPatterns("/*" ); return filterRegistrationBean; } }
로그인 후 Redirect 해주기 @PostMapping("/login") public String loginV4 (@Valid @ModelAttribute LoginForm form , BindingResult bindingResult , HttpServletRequest request , @RequestParam(defaultValue = "/") String redirectURL ) { log.info("Request Params : {}" , form); if (bindingResult.hasErrors()){ return "login/loginForm" ; } Member loginMember = loginService.login(form.getLoginId(), form.getPassword()); if (loginMember == null ){ bindingResult.reject("loginFail" , "아이디 또는 비밀번호가 맞지 않습니다." ); return "login/loginForm" ; } HttpSession session = request.getSession(); session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember); return "redirect:" + redirectURL; }