import hello.login.web.filter.LogFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean<Filter> logFilter(){
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new LogFilter());
filterFilterRegistrationBean.setOrder(1);
filterFilterRegistrationBean.addUrlPatterns("/*");
return filterFilterRegistrationBean;
}
}
로그 출력
필터를 등록할 때 `urlPattern` 을 `/*`로 등록했기 때문에 모든 요청에 해당 필터가 적용된다.
필터를 등록하는 방법은 여러가지가 있지만, 스프링 부트를 사용한다면 `FilterRegistrationBean` 을 사용해서 등록하면 된다. - `setFilter(new LogFilter())` : 등록할 필터를 지정한다. - `setOrder(1)` : 필터는 체인으로 동작한다. 따라서 순서가 필요하다. 낮을 수록 먼저 동작한다. - `addUrlPatterns("/*")` : 필터를 적용할 URL 패턴을 지정한다. 한번에 여러 패턴을 지정할 수 있다.
참고 실무에서 HTTP 요청시 같은 요청의 로그에 모두 같은 식별자를 자동으로 남기는 방법은 logback mdc로 검색해보자
서블릿 필터 - 인증 체크
인증 체크 필터를 개발 로그인 되지 않은 사용자는 상품 관리 뿐만 아니라 미래에 개발될 페이지에도 접근하지 못하도록 하자
LoginCheckFilter - 인증 체크 필터
@Slf4j
public class LoginCheckFilter implements Filter {
private static final String[] whitelist = {"/","members/add","/login","logout","/css/*"}; // 로그인 X 사용자 접근 가능
@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);
}
}
- `return;` ㄴ여기가중요하다. 필터를 더는 진행하지 않는다. 이후 필터는 물론 서블릿, 컨트롤러가 더는호출되지않는다. 앞서`redirect` 를사용했기때문에`redirect` 가응답으로적용되고요청이끝난다.
WebConfig - loginCheckFilter() 추가
import hello.login.web.filter.LogFilter;
import hello.login.web.filter.LoginCheckFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean<Filter> logFilter(){
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new LogFilter());
filterFilterRegistrationBean.setOrder(1);
filterFilterRegistrationBean.addUrlPatterns("/*");
return filterFilterRegistrationBean;
}
@Bean
public FilterRegistrationBean<Filter> loginCheckFilter(){
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new LoginCheckFilter());
filterFilterRegistrationBean.setOrder(2);
filterFilterRegistrationBean.addUrlPatterns("/*"); //화이트 리스트 빼고 로그인 인증 다함
return filterFilterRegistrationBean;
}
}
http://localhost:8080/items 로 접근하면 로그인 페이지로 리다이렉트 된다.
로그 출력 - `setFilter(new LoginCheckFilter())` : 로그인 필터를 등록한다. - `setOrder(2)` : 순서를 2번으로 잡았다. 로그 필터 다음에 로그인 필터가 적용된다. - `addUrlPatterns("/*")` : 모든 요청에 로그인 필터를 적용한다.
RedirectURL 처리
@PostMapping("/login")
public String loginV4(@Validated @ModelAttribute LoginForm loginForm , BindingResult bindingResult,
@RequestParam(defaultValue = "/") String redirectURL,
HttpServletRequest request){
if(bindingResult.hasErrors()){
return "login/loginForm";
}
Member loginMember = loginService.login(loginForm.getLoginId(), loginForm.getPassword());
if (loginMember == null){
bindingResult.reject("loginFail","아이디 또는 비밀번호가 맞지 않습니다.");
return "login/loginForm";
}
//로그인 성공 처리 TODO
//세션이 있으면 있는 세션 반환, 없으면 신규 세션을 생성
HttpSession session = request.getSession();
//세션에 로그인 회원 정보 보관
session.setAttribute(SessionConst.LOGIN_MEMBER,loginMember);
return "redirect:"+ redirectURL;
}
로그인하면 바로 items 페이지로 이동
- 로그인 체크 필터에서, 미인증 사용자는 요청 경로를 포함해서 `/login` 에 `redirectURL` 요청 파라미터를 추가해서 요청했다. 이 값을 사용해서 로그인 성공시 해당 경로로 고객을 `redirect` 한다.