TIL

+23 스프링부트 필터 Filter

JAVABOZA 2023. 7. 7. 11:40

스프링 부트에서 필터(Filter)는 클라이언트와 서버 간의 통신에서 요청과 응답을 가로채어 처리하는 역할을 수행합니다. 필터는 서블릿 컨테이너 내에서 작동하며, 클라이언트의 요청이 서블릿으로 전달되기 전이나 응답이 클라이언트에게 전송되기 전에 중간에서 작업을 수행할 수 있습니다.

 

 

 

@slf4j

로그 수행 작업을 하려면 해당 에노테이션을 사용

 

Filter Chain

필터체인은 필터는 우선 한개만 존재하는 것이 아니다. 여러개가 chain 형식으로 묶여서 처리가 가능하다

필터체인

@Order

필터의 순서를 정함

 

 

 

필터의 기능 중 인증 및 인가 처리 필터

@Slf4j(topic = "AuthFilter")
@Component
@Order(2)
public class AuthFilter implements Filter {
	// UserRepository, JwtUtil 해당 기능을 사용하기 위해 주입
    private final UserRepository userRepository;
    private final JwtUtil jwtUtil;
    
    // 생성자
    public AuthFilter(UserRepository userRepository, JwtUtil jwtUtil) {
        this.userRepository = userRepository;
        this.jwtUtil = jwtUtil;
    }
	
    //인터페이스 Filter에 doFilter메서드 오버라이드
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        
        // getRequestURI() url 정보를 가지고 와서 스트링 타입으로 url에 담음 (인가 처리)
        String url = httpServletRequest.getRequestURI();
        
		// 해당 URL들은 인증처리에서 제외 시키려고 if 문에 담음
        if (StringUtils.hasText(url) &&
                (url.startsWith("/api/user") || url.startsWith("/css") || url.startsWith("/js"))
        ) {
            // 회원가입, 로그인 관련 API 는 인증 필요없이 요청 진행
            chain.doFilter(request, response); // 다음 Filter 로 이동
        } else {
            // 나머지 API 요청은 인증 처리 진행
            // httpServletRequest에서 쿠키 목록 가지고 와서 jwt에 저장된 쿠키 찾음
            String tokenValue = jwtUtil.getTokenFromRequest(httpServletRequest);

            if (StringUtils.hasText(tokenValue)) { // 토큰이 존재하면 검증 시작
                // JWT 토큰 substring
                String token = jwtUtil.substringToken(tokenValue);

                // 토큰 검증
                if (!jwtUtil.validateToken(token)) {
                    throw new IllegalArgumentException("Token Error");
                }

                // 토큰에서 사용자 정보 가져오기
                Claims info = jwtUtil.getUserInfoFromToken(token);

                User user = userRepository.findByUsername(info.getSubject()).orElseThrow(() ->
                        new NullPointerException("Not Found User")
                );
				//setAttribute메서드는 "user"로 키값을 하고 그에 해당하는 value user값을 가져온다
                request.setAttribute("user", user);
                
                // 다음 Filter 로 이동
                chain.doFilter(request, response); 
            } else {
                throw new IllegalArgumentException("Not Found Token");
            }
        }
    }

}
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
캐스팅 하는 이유?

이 인터페이스는 HTTP요청 및 응답에 트고하된 메서드와 속성을 포함하지 않고 있음

HttpServletRequestServletRequest 하위 인터페이스로 HTTP프로토콜에 특화된 메서드와 속성을 제공함

 

예를 들어서 gerRequestURI() 메서드를 사용하여 현재 요청의 URI를 가져 올 수 있음

 

Filter에서는 주로 HTTP 요청과 응답에 대한 정보를 처리해야하는 경우가 많다.

그래서 HttpServletRequest 로 캐스팅해서 HTTP요청에 대한 정보에 접근 가능하려 한다.

 

요약하면
HttpServletRequest 로의 캐스팅은 Filter에서 http 요청에 접근하기 위해 ServletRequest를 http-specific인터페이스로 변환하는 역할을 한다. 이를 통해서 http요청의 url 및 기타 http 특정 정보를 필터에서 사용 할 수 있게 한다.