💻본 포스팅은 '스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 김영한'님의 강의를 듣고 작성되었습니다.
목차
1. 공통의 관심 사항
- 서블릿 필터
- 스프링 인터셉터
2. 서블릿 필터
3. 서블릿 필터 정리
공통의 관심 사항
- 예
- 로그인 한 사용자만 상품 관리 페이지에 들어갈 수 있어야 한다는 요구사항이 있을 경우 개발자는 로그인 하지 않은 권한 없는 사람이 접근 제한한 부분을 들어가는 것을 기술적으로 막아두어야 한다.
- 이때 로그인 하지 않을 때 꽤나 많은 접근의 제한이 있어야 하고 우리는 이를 위해 로그인 여부 체크하는 로직을 하나 넣어주면 되지만 매우 많은 컨트롤러에 공통으로 로그인 여부를 체크해주어야 하기에 상황이 복잡해진다.
- 이처럼 공통으로 인증(로그인 했는지 안 했는지)에 관심을 가지고 있는 경우를 공통 관심사라고 한다.
- 스프링의 AOP로 공통 관심사 문제를 해결할 수 있지만 웹과 관련된 공통 관심사의 경우엔 서블릿 필터, 혹은 스프링이 제공하는 인터셉터를 사용하는 것이 바람직하다.
- 웹과 관련된 공통 관심사 처리는 HTTP 헤더나 URL 정보들이 필요하고 서블릿 필터와 스프링의 인터셉터는 HttpServletRequest를 제공해 이 문제를 처리할 수 있게 한다.
서블릿 필터
필터는 서블릿이 지원하는 수문장이라고 생각하면 편하다.
필터의 특성
필터 흐름
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러
필터 제한
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러 //로그인 사용자
HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단, 서블릿 호출X) //비로그인 사용자
필터에서 적절하지 않은 요청이라고 판단하면 서블릿까지 가지 않게 해서 끝을 내준다. (이때 로그인 여부를 확인하기에 좋다.)
필터 체인
HTTP 요청 -> WAS -> 필터1 -> 필터2 -> 필터3 -> 서블릿 -> 컨트롤러
필터는 체인으로 구성되어 있고 중간에 필터를 자유롭게 추가할 수 있다.
서블릿 필터 - 요청로그
모든 요청을 로그로 남기는 필터
필터의 경우엔 FilterRegistrationBean를 사용해서 Bean등록을 해주어야 사용할 수 있다.
서블릿 필터 - 인증 체크
로그인 하지 않은 사용자는 상품 관리뿐만 아닌 미래에 개발되고 수정될 페이지에 접근할 수 없는 경우에도 접근할 수 없게 하자
인증 체크 필터
package hello.login.web.filter;
import hello.login.web.session.SessionConst;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.PatternMatchUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@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; //여기서가 중요 인증하지 않은 사용자라면 요청을 끝내야 됨(서블릿, 컨트롤러 호출 X)
}
}
chain.doFilter(request,response);
} catch (Exception e){
throw e;//예외 로깅 가능하지만 톰캣까지 예외를 보내주어야 한다.
} finally {
log.info("인증 체크 필터 종료{}", requestURI);
}
}
//화이트 리스트의 경우 인증 체크 X
private boolean isLoginCheckPath(String requestURI){
return !PatternMatchUtils.simpleMatch(whiteList, requestURI);
}
}
- whiteList에는 로그인 없이도 접근 가능한 페이지를 허용할 수 있게 담아주어야 한다.
- 회원가입이나 로그인 화면과 같은 부분은 로그인 하지 않은 사용자도 접근할 수 있어야 하기때문이다.
- 인증을 하지 않은 사용자라면 다음 단계로 나가지 않게 끝내주어야 한다.(컨트롤러를 호출하게 되면 인증 없이도 접근 가능해지게 된다.)
필터 등록
package hello.login;
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 logFilter(){
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new Logfilter());
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;
}
}
서블릿 필터 정리
- 서블릿 필터를 잘 사용하면 로그인 하지 않은 사용자가 허용하지 않은 경로로 가는 것을 막을 수 있다.
- 공통의 관심사를 서블릿 필터를 사용해서 해결한 덕분에 향후 로그인 관련 정책의 변경이 있더라도 이 부분만 변경하면 되게 된다.
'Back-End > Spring' 카테고리의 다른 글
[Spring MVC2][예외 처리와 오류 페이지] - 서블릿 예외 처리 (0) | 2022.05.28 |
---|---|
[Spring MVC2][로그인 처리] - 스프링 인터셉터(공통의 관심사 해결 방안) (0) | 2022.05.20 |
[Spring MVC2][로그인 처리] - 쿠키와 세션 (0) | 2022.05.17 |
[Spring MVC2][로그인 처리] - 로그인 기능(로그인 서비스 로직) (0) | 2022.05.13 |
[Spring MVC2][로그인 처리] - 회원가입 처리 (0) | 2022.05.13 |