필터 흐름
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러 // 로그인 사용자
HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단, 서블릿 호출X) // 비 로그인 사용자
- init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출
- doFilter(): 고객의 요청이 올 때 마다 해당 메서드가 호출 (필터 로직을 구현)
- destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출
서블릿 필터
인증 체크 필터 개발
// 필터를 사용하려면 필터 인터페이스를 구현해야 함
@Slf4j
public class LoginCheckFilter implements Filter {
// 화이트 리스트를 제외한 나머지 모든 경로에 인증 체크 로직을 적용
private static final String[] whiteList = {"/", "/members/add", "/login", "/logout", "/css/*"};
// HTTP 요청이 오면 doFilter 호출
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// ServletRequest request는 HTTP 요청이 아닌 경우까지 고려해서 만든 인터페이스 -> HTTP 사용시 다운 케스팅
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
if (isLoginCheckPath(requestURI)) { // 인증 체크
HttpSession session = httpRequest.getSession(false);
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) { // 미인증 사용자
httpResponse.sendRedirect("/login?redirectURL=" + requestURI); // 로그인으로 redirect
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);
}
WebConfig - 필터 등록 → FilterRegistrationBean 사용
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean loginCheckFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LoginCheckFilter());
filterRegistrationBean.setOrder(2);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
- setFilter(new LoginCheckFilter()) : 등록할 필터를 지정
- setOrder(2) : 필터는 체인으로 동작하여 순서가 필요 → 낮을 수록 먼저 동작
- addUrlPatterns("/*") : 필터를 적용할 URL 패턴을 지정 → 한번에 여러 패턴을 지정 가능
스프링 인터셉터
스프링 인터셉터 흐름
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러 // 로그인 사용자
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 (적절하지 않은 요청이라 판단, 컨트롤러 호출 X) // 비 로그인 사용자
스프링 인터셉터 호출 흐름
- preHandle : 컨트롤러 호출 전에 호출 (핸들러 어댑터 호출 전에 호출)
- preHandle의 응답값이 true이면 다음으로 진행하고, false이면 더는 진행하지 않음
- postHandle : 컨트롤러 호출 후에 호출 (핸들러 어댑터 호출 후에 호출), 예외가 발생되면 호출되지 않음
- afterCompletion : 뷰가 렌더링 된 이후에 호출, 항상 호출되어 예외가 발생한 경우 예외를 로그로 출력 가능
인증 체크 기능 개발
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
HttpSession session = request.getSession();
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
response.sendRedirect("/login?redirectURL=" + requestURI); // 로그인으로 redirect
return false;
}
return true;
}
}
WebConfig - 인터셉터 등록 (순서 주의, 세밀한 설정 가능)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor())
.order(1)
.addPathPatterns("/**")
.excludePathPatterns("/css/**", "/*.ico", "/error");
registry.addInterceptor(new LoginCheckInterceptor())
.order(2)
.addPathPatterns("/**")
.excludePathPatterns("/", "/members/add", "/login", "/logout",
"/css/**", "/*.ico", "/error");
}
- registry.addInterceptor(new LogInterceptor()) : 인터셉터를 등록
- order(1) : 인터셉터의 호출 순서를 지정 → 낮을 수록 먼저 호출
- addPathPatterns("/**") : 인터셉터를 적용할 URL 패턴을 지정
- excludePathPatterns("/css/**", "/*.ico", "/error") : 인터셉터에서 제외할 패턴을 지정
참고 강의:
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의
웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있
www.inflearn.com
'Spring Boot' 카테고리의 다른 글
단위 테스트(Unit Test)와 통합 테스트 (0) | 2023.08.20 |
---|---|
API 예외 처리 (0) | 2023.07.12 |
쿠키, 세션 - 스프링 적용 (0) | 2023.07.10 |
Validation (0) | 2023.07.05 |
Thymeleaf - 스프링 통합과 폼 (0) | 2023.07.04 |