SpringBoot

Interceptors & Filters

요는 2022. 3. 24. 12:25

1. Filter & Interceptor 기본 개념

 

모든 사용자가 같이 필요한 기능

ex ) 로그인, 보안

 

일반적인 spring application의 모습

 

springboot는 tomcat이 둘러싸게 됨 = web container

 

 

1. Filter

보안을 구현하기 위해 filter 사용

- springboot 외부에 있는 기능

- 외부client과 dispatcher servlet 사이에 들어옴

- Filter : jakarta servlet api의 일부 

- spring framework의 일부분이 아니라 java로 만든 웹서버에서 사용하게 되는 interface

- springapplication에 도달하기 전에 모든 요청 막아 낼 수 있음 

- 한개의 함수만 존재

doFilter() 함수
​인자로 ServeletRequest , ServeltResponse , FilterChain 받음
- http servelet resquest response보다 한단계 더 위 -> serveletReques, response를 상속받는 개체들임
- 모호한 객체 사용 이유 : ServeletRequest, Response를 조작가능. 
- FilterChain : 여러개의 filter중 chain이라는 FilterChain에 속해있는 doFilter 호출 -> 모든 filter들이 호출됨

2. Interceptor

- 내부에서 구현

- fullname = HandlerInterceptor : handler mapping에 대한 요청 처리위한 interceptor

- 3개의 함수 존재

preHandle()
- controller로 요청 들어가기 전
- preHandle과 postHandle 사이에서 controller와 model에 대한 조작 일어남

postHandle()

- controller에서 응답 만들고 난뒤
 - postHandle과 afterCompletion사이에서 요청의 전달 일어남
- 인자 ModelAndView : 추가적인 정보 더 넣어 줄 수 있음
afterCompletion()
- 응답을 client한테 보내고 난 뒤 
- view가 랜더 되고 사용자한테 이미 전달이 된 뒤 

 

3. 차이

 

 

둘다 java server, spring framework에서 제공하는 기능

- AOP : reflection = 함수의 이름을 실행중에 알아내서 그에 따른 행동을 바꿔주고 string으로 바꿔 비교가 가능하게 함

- Interceptor와 Filter : 요청과 응답이 오고가는 와중에 기능 적용할 interface에 불과

더 간단

 

예외처리 : 대부분 spring framework 안에서 작동

= interceptor에서 발생한 예외는 처리 가능한데 filter에서 발생하면 처리 불가능함

 


2. Filter 구현하기

1. 실습

package filter 만들기

 

1) TransactionLogFilter

어떤 요청이 들어오고 그 요청이 어떤 status 코드를 가지고 돌아갔는지 확인

servelet의 filter을 선택

public clas TransactionLogFilter implements Filter{
	privat static final Logger logger = LoggerFactory.getLogger(TransactionFilter.class);
	@Override
    public void doFilter(
    	ServletRequest requet,
        ServletResponse response,
        FilterChain chain) throws IOException, ServletException{
    String requestUUID = UUID.randomUUID().toString().split("-")[0]; //구분자
    HttpServletRequest httpservletRequest = (HttpServletRequest) request;
    logger.debug("[{}] start request : {} {}",
    		requestUUID, 
            httpServletRequest.getMethod(), 
            httpServletRequest.getRequestURI()
    );
        }
       }

chain의 doFilter 호출하기 전까지의 상황 / filter의 요청이 spring으로 넘어가기 전

 

- request 확인하기

더보기

HttpServletRequest httpservletRequest = (HttpServletRequest) request;

3) chain의 doFilter 호출하기

 

@Component
public class TransactionLogFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(TransactionLogFilter.class);

    @Override
    public void doFilter(
            ServletRequest request,
            ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        String requestUUID = UUID.randomUUID().toString().split("-")[0];
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        logger.debug("[{}] start request: {} {}",
                requestUUID,
                httpServletRequest.getMethod(),
                httpServletRequest.getRequestURI()
        );
    logger.info("*response status code : {}", ((HttpServletResponse) response).getStatus());
    chain.doFilter(request, response);
    
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    logger.info(" *response status code:{}", ((HttpServletResponse) response).getStatus());
    logger.info("[{}], send response : {}",
    	requestUUID, httpServletResponse.getStatus());
        }
       }

 


3. HandlerInterceptor 구현하기

1. 실습

package interceptor 생성

1) HeaderLoggingInterceptor

@Component
public class HeaderLoggingInterceptor implements HandlerInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(HeaderLoggingInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler; //형변환
        logger.info("start processing of {}", handlerMethod.getMethod().getName()); //
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            logger.trace("{}: {}", headerName, request.getHeader(headerName));
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        Collection<String> headerNames = response.getHeaderNames();
        for (String headerName: headerNames) {
            logger.trace("{}: {}", headerName, response.getHeader(headerName));
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        logger.info("completed processing of {}", handlerMethod.getMethod().getName());
        if (ex != null) logger.error("Exception occurred while processing", ex);
    }
}

 

 Enumeration 
eterator와 비슷하게 작동 / hasMoreElements를 대신 사용

 

Collection
response의 interface는 enumeration이 아니라 collection

 

2) 등록하기

만들었다고 끝아님 configuration bean안에 등록해줌

DemoConfiguration

@Configuration
public class DemoConfiguration implements WebMvcConfigurer{
	private static final Logger logger = LoggerFactory.getLogger(DemoConfiguration.class);
    
    private final HeaderLoggingInterceptor headerLoggingInterceptor;
    
    public DemoConfiguration(
    	@Autowired HeaderLoggingInterceptor headerLoggingInterceptor){
        this.headerLoggingInterceptor = headerLoggingInterceptor;}
     
    
    @Override
    public void addInterceptors(InterceptorRegistry registry){
    	registry
        		.addInterceptor(headeLogginInterceptor) 
                .addPathPattterns("/post/**");
                .excludePathPatterns("/except/**");
                }

 

addInterceptors 함수

interceptor를 만들고 등록하고 싶을 때 사용하는 함수

 

하고 싶은 interceptor 오기

더보기

private final HeaderLoggingInterceptor headerLoggingInterceptor;
    
    public DemoConfiguration(
     @Autowired HeaderLoggingInterceptor headerLoggingInterceptor){
        this.headerLoggingInterceptor = headerLoggingInterceptor;}

 

'SpringBoot' 카테고리의 다른 글

Exception Handling - 강의 정리  (0) 2022.03.24
Validation - 강의정리  (0) 2022.03.22
Spring AOP -강의정리  (0) 2022.03.22
Logging -강의  (0) 2022.03.22
Spring Boot Properties - 강의 정리  (0) 2022.03.22