🔒 필터, 인터셉터 사용 예시
- 로그인된 사람들만 특가를 확인하도록 할 때
- 모니터링만 할 수 있고 데이터 조작은 안되는 관리자모드 설정 할 때
Filter 인터페이스
상속// 필터 인터페이스 구현
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 {
//request, response 생성
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
System.out.println("인증 필터 체크 시작 : " + requestURI);
/* whitelist가 아닌 URI만을 검증 */
if( isLoginCheckPath(requestURI) ) {
/* session에 값 x -> 단순 url로 들어온 것
미인증 된 사람 = 로그인 안 되어 있는 사람 */
HttpSession session = httpRequest.getSession(false);
if( session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null ) {
// 로그인창으로 redirect
// 예를들어, 내가 로그인 하지 않은 상태로 items url을 접근
// -> 로그인 페이지가 보여져야 한다.
httpResponse.sendRedirect("/login?redirectURL="+requestURI);
return; // **중요 : 미 인증 사용자는 다음으로 진행하지않고 종료
}
}
// if문 다음으로 진행
chain.doFilter(request, response);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("인증 체크 필터 종료 : " + requestURI);
}
}
// whitelist인지 아닌지 체크 : whitelist인 경우 인증 체크 하지 않음
private boolean isLoginCheckPath(String requestURI) {
// !를 넣음으로서 whitelist에 없을 때 return하도록
return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
}
}
- PatternMatchUtils
- 간단한 패턴 매치 판별해주는 유틸
return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
- 들어온 uri가 whitelist에 있는 지 확인
① private static final String[] whitelist = {"/", "/members/add", "/login", "/logout", "/css/*"};
②isLoginCheckPath(String requestURI)
③ return;
④ httpResponse.sendRedirect("/login?redirectURL="+requestURI);
/login?redirectURL="+requestURI
- 사용자가 들어가고 싶어하는 페이지를 파라미터로 로그인 페이지를 열어줌
- 로그인이 완료된 후 해당 페이지로 넘어가려면 login controller에서 한번 더 처리 필요
@PostMapping("/login") public String loginv3(@ModelAttribute LoginForm form, Model model, RedirectAttributes redirectAttributes, HttpServletRequest request, // @RequestParam(defaultValue = "/") 추가 : 로그인 완료 된 후 사용자가 원하는 페이지로 넘어갈 수 있도록 @RequestParam(defaultValue = "/") String redirectURL // 파라미터가 없으면 /, 있으면 redirectURL에 넣어줌 ) { ~ 로그인 로직 ~ return "redirect:" + redirectURL; }
- jsessionID 숨겨주기 > application.properties에 추가
#jsessionID 노출되지 않도록 server.servlet.session.tracking-modes=cookie
@Configuration
@Bean
FilterRegistrationBean
: 필터 등록 시 사용//@Configuration
public class WebConfig {
// @Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean
= new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LoginCheckFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
①filterRegistrationBean.setFilter(new 필터생성className())
filterRegistrationBean.setOrder(1)
filterRegistrationBean.addUrlPatterns("/*")
/*
: 전체 경로 HandlerIntercepter 인터페이스
를 구현doFilter()
1개, 인터셉터는 3개로 세분화preHandle
: 컨트롤러 호출 전에 호출postHandle
: 컨트롤러 호출 후에 호출afterHandle
: 뷰가 렌더링 된 이후에 호출public class LogIntercepter implements HandlerInterceptor{
public static final String LOG_ID = "logId";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestURI = request.getRequestURI();
String uuid = UUID.randomUUID().toString();
request.setAttribute(LOG_ID, uuid);
System.out.println("[intercepter] uuid : " + uuid);
System.out.println("[intercepter] requestURI : " + requestURI);
return true; // false로 전환시 진행하지 않음
}
// 컨트롤러 호출 후 modelAndView
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("[intercepter] postHandle : " + modelAndView);
}
// 뷰가 렌더리 된 후 logId, requestURI 출력
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
String requestURI = request.getRequestURI();
String logId = (String)request.getAttribute(LOG_ID);
// pre에서 해놨던 랜덤 값을 after에서 한번 더 꺼내옴
System.out.println("[intercepter] logId : " + logId);
System.out.println("[intercepter] requestURI : " + requestURI);
}
}
preHandle
만 사용public class LoginCheckInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestURI = request.getRequestURI();
System.out.println("[인증 체크 인터셉터 실행] : " + requestURI);
// 아이디에 대한 정보 session으로 받기
HttpSession session = request.getSession(false);
if( session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null ) {
System.out.println("[미인증 사용자 요청]");
// 로그인으로 redirect
response.sendRedirect("/login?redirectURL="+requestURI);
return false;
}
return true;
}
}
@Configuration
: filter와 똑같이 어노테이션 적용WebMvcConfigurer
인터페이스 상속@Configuration
public class WebConfig2 implements WebMvcConfigurer{
registry.addInterceptor(new LoginCheckInterceptor())
.order(1)
.addPathPatterns("/**") // 모든 경로 전체 가능
.excludePathPatterns("/", "/members/add", "/login", "/logout", "/css/**"); // 이 경로들을 제외
}
}
.addInterceptor(new 인터페이스생성className())
.order(1)
.addPathPatterns("/**")
.excludePathPatterns("/css/**", "/*.ico", "/error");
인터셉터 경로
/**
- 모든 경로에 대해서 적용할때
- 예 :
/css/**
/*
- 1개의 어떠한 경로에 상관없이 사용, 2번째 경로를 조율하고 싶을 때
- 예 :
/*.ico