지금까지 사용자 입력 값을 검증하기 위한 여러 검증 방법과 로그인을 유지하기 위한 방법으로 쿠키, 세션에 대해 알아보았다.
쿠키, 세션을 사용하여 로그인을 한 사용자한테만 메인 화면을 보여주도록 설계를 했는데 만약에 로그인을 하지 않은 사용자가 직접 URL로 메인 화면을 호출을 하면 어떻게 될까?
각각의 컨트롤러에서 전부 로그인 여부를 체크하는 것이 아니라면 로그인을 하지 않아도 URL로 접근이 가능할 것이다.
이렇게 애플리케이션 여러 로직에서 공통으로 관심이 있는 것을 공통 관심사라고 한다. 이러한 공통 관심사는 스프링의 AOP로 해결할 수도 있지만 웹과 관련된 공통 관심사는 서블릿의 필터 또는 스프링의 인터셉터를 사용하는 것이 좋다.
서블릿 필터
서블릿 필터는 WAS에서 서블릿(DispatcherServlet)을 호출하기 전에 작동하며, 특정 URL 요청에 대해 적절하지 않은 요청의 경우 서블릿으로 넘어가지 않도록 필터 역할을 한다.
필터는 체인 기능을 통해 여러 개의 필터를 추가할 수 있으며 다음의 메서드를 오버라이드해서 필터 인터페이스를 구현한다.
- init() : 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출
- doFilter(): 요청이 올 때 마다 호출되는 메서드로, 필터의 로직을 담당
- destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
...
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
String uuid = UUID.randomUUID().toString();
try {
// 다음 필터를 호출하고, 다음 필터가 없을 경우 서블릿을 호출하는 필수 로직
chain.doFilter(request, response);
} catch (Exception e) {
throw e;
} finally {
...
}
}
@Override
public void destroy() {
...
}
}
이렇게 만든 필터를 등록하는 방법은 여러가지가 있지만, 스프링 부트를 사용하는 경우 FilterRegistrationBean을 사용해서 등록하면 된다.
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
// 등록할 필터 지정
filterRegistrationBean.setFilter(new LogFilter());
// 필터 체인 우선 순위, 1이면 먼저 동작
filterRegistrationBean.setOrder(1);
// 필터를 적용할 URL 패턴
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
모든 URL에 대해 필터를 적용한다해도 홈, 회원가입, 로그인 화면, css 같은 리소스에는 접근할 수 있어야 하는데 예외적인 경로를 따로 배열로 만들어서 제외시킬 수 있다.
public class LoginCheckFilter implements Filter {
private static final String[] whitelist = {"/", "/login", "/logout","/css/*"};
@Override
public void doFilter(...) {
try {
if (isLoginCheckPath(requestURI)) {
HttpSession session = httpRequest.getSession(false);
if (session == null || session.getAttribute("loginMember") == null) {
httpResponse.sendRedirect("/login?redirectURL=" + requestURI);
return;
}
}
// 세션이 없을 경우 리턴, 아니면 다음 필터로
chain.doFilter(request, response);
} catch (Exception e) {
throw e;
} finally {
...
}
}
// whitelist의 경로일 경우 인증 체크 X
private boolean isLoginCheckPath(String requestURI) {
return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
}
[참고] 인프런 김영한님 강의를 공부한 내용입니다.
'Spring' 카테고리의 다른 글
[스프링 MVC2] 예외 처리와 오류 페이지 (0) | 2022.06.17 |
---|---|
[스프링 MVC2] 스프링 인터셉터 (0) | 2022.06.16 |
[스프링 MVC2] 쿠키와 세션 (0) | 2022.06.16 |
[스프링 MVC2] 애노테이션 검증 (Bean Validation) (0) | 2022.06.15 |
[스프링 MVC2] 메시지, 국제화 (0) | 2022.06.15 |