로그인 필터가 제대로 작동하지 않는 현상

pickylemon·2024년 5월 10일

Exception 모음

목록 보기
11/31

상황

로그인 검증이 필요한 페이지들에 각각 중복 로직을 두지 않고
로그인 필터를 만들어서 공통으로 처리하려는 상황

1) 필터에서 로그인 검증이 필요한 매핑인지를 검사 후,
2) Session에 memberSeq가 있는지 검사해서 (로그인 성공하면 session에 memberSeq 저장함)
3) memberSeq가 없거나 session이 null이면 로그인 페이지로 redirect시키는 로직이었다.

분명, if문에도 의도한 바에 맞게 잘 들어갔는데, 이상하게 로그를 보면 로그인 페이지로 바로 redirect가 되지 않았다.

//LoginFilter.java
@Slf4j
public class LoginFilter implements Filter {
	
	private String[] urlMapping = { 
			LoginAuthEnum.BOARD.getUrl(), 
			LoginAuthEnum.DEVELOP.getUrl(), 
			LoginAuthEnum.SALES.getUrl(),
			LoginAuthEnum.QA.getUrl(),
			LoginAuthEnum.SUPPORT.getUrl()};

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		String requestURL = request.getRequestURL().toString();
		String contextPath = request.getContextPath();
		String requestURI = request.getRequestURI().replace(contextPath,"");
		HttpSession session = request.getSession(false);
        //있는 세션에 대해서만 반환하도록 매개변수를 false로 줌.
		
		log.info("referer={}", request.getHeader("referer"));
		log.info("requestURI={}", request.getRequestURI());		
		log.info("contextPath={}", contextPath);
		log.info("requestURL = {}", requestURL);
		log.info("requestURI = {}", requestURI);
		
		//로그인 인증이 필요한 페이지에 한해 로그인 검증
		List<String> urlList = List.of(urlMapping);
		if(urlList.stream().anyMatch(url -> requestURI.startsWith(url))) {
			log.info("로그인 검증 대상 페이지");
			//로그인이 되어 있지 않으면 로그인 페이지로 redirect
			if(session == null || ObjectUtils.isEmpty(session.getAttribute("memberSeq"))) {
				log.info("로그인 페이지로 이동");
				response.sendRedirect(contextPath+"/loginPage.do?url="+requestURL);

			}
		}
		chain.doFilter(request, response);
	}
}

  • 분명 if문 안으로 들어왔는데, loginPage로 바로 redirect되지 않고,
    원래 가려던 listPage.do에 매핑된 메서드 안으로 들어가서 로직을 수행한다.

문제 및 해결

  • 역시 자바가 근본이고 중요하다.
  • response.sendRedirect 이후에 꼭!! return문을 넣어주어야 한다.
  • return문이 없으니 아래 로직까지 다 실행되어 버린 것.
response.sendRedirect(contextPath+"/loginPage.do?url="+requestURL);
return;
//아래에서 chain.doFilter()을 호출할 거라면 반드시 return을 적어주어야 한다. 

조금 더 알아보기

  • response.sendRedirect()
    • response.sendRedirect()를 호출하면, 매개변수로 넣어준 URL을 redirect location삼아 응답코드 302로 redirect 응답을 내보낸다.(응답 버퍼를 비우고 커밋한다.)
    • response.sendRedirect()가 보내는 응답은 헤더만 있고 바디가 없어서 response.sendRedirect()호출 후에는 response에 추가로 무언가를 더 쓸 수 없음에 주의. (이 메서드를 호출하면 응답은 commit된 거라고 친다)
    • 이미 commit된 response에 대해서 호출할 경우 IllegalStateException 발생
    • 매개변수로는 절대주소, 상대주소 모두 넣을 수 있고 leading '/' 슬래시에 따라 해석이 달라진다.
profile
안녕하세요

0개의 댓글