mvc 2 로그인 처리하기(인터셉터)

이주인·2023년 2월 8일
0

스프링 공부

목록 보기
7/11
post-thumbnail

인터셉터

공통 관심사

  • 여러 로직에서 공통으로 관심이 있는 것
  • 보통 서블릿 필터나 스프링 인터셉터를 사용한다.
  • 이때 HTTP 헤더나 URL의 정보들을 조회하기 위해 HttpServletRequest를 제공

스프링 인터셉터의 흐름

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러

스프링 인터셉터는 체인으로 구성되며, 중간에 인터셉터를 자유롭게 추가할 수 있다.

서블릿 필터와 스프링 인터셉터는 웹과 관련된 공통 관심사를 해결하기 위한 기술이며, 인터셉터가 좀더 구현하기 편리하다.
특별한 문제가 없다면 인터셉터를 사용하는 것이 좋다

HandlerInterceptor

스프링 인터셉터를 사용하기위한 인터페이스
3가지 메소드가 존재한다.

  1. preHandle(컨트롤러 호출 전)
    • 응답 값이 true면 다음으로 진행
    • false면 호출중지
  2. postHanlde(컨트롤러 호출 후)
  3. afterCompletion(요청 완료 이후)
    • 뷰가 렌더링 된 후 호출
    • 예외가 발생해도 호출되며 예외 정보를 포함해서 호출된다.
      -> 예외와 무관하게 공통처리를 하려면 이 메소드를 사용해야 한다.

요청로그

@Slf4j
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();
        //요청 로그를 구분하기 위한 uuid
        String uuid = UUID.randomUUID().toString();
		
        /*
		preHandle에서 지정한 값을 사용하기위해 request에 담아둔다
        -> 호출 시점이 분리 되어 있어 함께 사용되지 않기 때문
        */
        request.setAttribute(LOG_ID, uuid);

        if (handler instanceof HandlerMethod){
            //호출할 컨트롤러 메서드의 모든 정보가 포함되어 있음
            HandlerMethod hm = (HandlerMethod) handler;

        }
        log.info("REQUEST [{}][{}][{}]", uuid, requestURI, handler);
        return true;
    }

	//컨트롤러 호출 후
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandler [{}]", modelAndView);
    }

	//요청 완료 이후
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String requestURI = request.getRequestURI();
        Object logId = (String)request.getAttribute(LOG_ID);
		
        //종료 로그 - 예외가 발생해도 호출되는 메소드이기 때문
        log.info("RESPONSE [{}][{}][{}]", logId, requestURI, handler);

        if (ex != null){
            log.error("after completion 에러!!", ex);
        }
    }
}


로그인 체크 로직

@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {

    //컨트롤러 호출전에만 호출되면 되므로,prehandle만 구현
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        log.info("인증 체크 인터셉터 실행 {}", requestURI);
        HttpSession session = request.getSession();

        if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null){
            log.info("미인증 사용자 요청");
            //로그인으로 리다이렉트
            response.sendRedirect("login?redirectURL=" + requestURI);
            return false;
        }

        return true;
    }
}

인증이 필요한 컨트롤러 호출 전에 호출 되므로, preHandle 메소드만 구현하면 된다.



WebConfig

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        //로그 출력 인터셉터
        registry.addInterceptor(new LogIntercepter())
                .order(1)
                .addPathPatterns("/**")
                .excludePathPatterns("/css/**", "/*.ico", "/error");

        //로그인 체크 인터셉터
        registry.addInterceptor(new LoginCheckInterceptor())
                .order(2)   //두번째로 작동
                .addPathPatterns("/**") //모든 경로에 대해 적용
                .excludePathPatterns("/", "/members/add", "/login", "/logout",
                        "/css/**", "/*.ico", "/error"); //단, 이경로는 인터셉터 제외
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new LoginMemberArgumentResolver());
    }

    

addInterceptors() : 인터셉터를 등록하는 메소드
.excludePathPatterns: 인터셉터에서 제외할 url 경로를 상세히 지정할 수 있다.

기타 - argumentresolver

profile
컴공

0개의 댓글