필터

금은체리·2023년 11월 16일
0

Spring

목록 보기
16/49

Filter란?

  • Web 애플리케이션에서 관리되는 영역
  • Client로부터 오는 요청과 응답에 대한 최초/최종 단계의 위치
  • 이를 통해 요청과 응답의 정보를 견경하거나 부가적인 기능 추가 가능

Filter Chain

  • Filter는 한 개만 존재하는 것이 아니라 이렇게 여러 개가 Chain 형식으로 묶여서 처리 가능

Filter 적용

📌 요청 URL의 인가 처리 및 인증 처리를 진행할 수 있는 Filter
+ 요청 URL을 로깅해주는 Filter rngus

  1. Request URL Logging
  • Slf4j(topic = "값")
    • Logging 찍힐 때 값으로 찍힘
  • @Order(1)
    • 필터의 순서 지정
  • implements Filter
    • doFilter 라는 메서드를 오버라이딩하면 Filter로서 역할 수행 가능
    • doFilter(ServletRequest, Servlet Response, FilterChain)
  • chain.doFilter(request, response);
    • 다음 Filter로 이동
  • log.info("비즈니스 로직 완료");
    • 작업이 다 완료된 후 Client에 응답 전 로그가 작성된 것을 확인 가능
  1. AuthFilter : 인증 및 인가 처리 필터
@Slf4j(topic = "AuthFilter")
@Component
@Order(2)
public class AuthFilter implements Filter {

    private final UserRepository userRepository;
    private final JwtUtil jwtUtil;

    public AuthFilter(UserRepository userRepository, JwtUtil jwtUtil) {
        this.userRepository = userRepository;
        this.jwtUtil = jwtUtil;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String url = httpServletRequest.getRequestURI();

        if (StringUtils.hasText(url) &&
                (url.startsWith("/api/user") || url.startsWith("/css") || url.startsWith("/js"))
        ) {
            // 회원가입, 로그인 관련 API 는 인증 필요없이 요청 진행
            chain.doFilter(request, response); // 다음 Filter 로 이동
        } else {
            // 나머지 API 요청은 인증 처리 진행
            // 토큰 확인
            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")
                );

                request.setAttribute("user", user);
                chain.doFilter(request, response); // 다음 Filter 로 이동
            } else {
                throw new IllegalArgumentException("Not Found Token");
            }
        }
    }

}
  • httpServletRequest.getRequestURI

    • 요청 URL을 가져와서 구분(인가)
    • "/api/user, "/css", "/js"로 시작하는 URL은 인증 처리에서 제외 시킴
  • 그 외 URL은 인증 처리 진행

    • jwtUtil.getTokenFromRequest(httpServletRequest);
      • httpServletRequest에서 Cookie 목록을 가져와 JWT가 저장된 Cookie를 찾음
      • getTokenFromRequest 메서드를 JwtUtil에 구현
          // HttpServletRequest 에서 Cookie Value : JWT 가져오기
        public String getTokenFromRequest(HttpServletRequest req) {
          Cookie[] cookies = req.getCookies();
          if(cookies != null) {
              for (Cookie cookie : cookies) {
                  if (cookie.getName().equals(AUTHORIZATION_HEADER)) {
                      try {
                          return URLDecoder.decode(cookie.getValue(), "UTF-8"); // Encode 되어 넘어간 Value 다시 Decode
                      } catch (UnsupportedEncodingException e) {
                          return null;
                      }
                  }
              }
          }
          return null;
        }
        		```
    • tokenValue가 존재하면 토큰 파싱, 검증을 진행하고 사용자 정보를 가져옴
    • 가져온 사용자 username을 사용해서 DB에 사용자가 존재하는지 확인하고 존재하면 인증이 완료된것임!
    • 사용자 정보가 필요한 Controller API에 인증완료된 User 객체를 전달해 줌
    	@Controller
    	@RequestMapping("/api")
    	public class ProductController {
    
        @GetMapping("/products")
        public String getProducts(HttpServletRequest req) {
            System.out.println("ProductController.getProducts : 인증 완료");
            User user = (User) req.getAttribute("user");
            System.out.println("user.getUsername() = " + user.getUsername());
    
           return "redirect:/";
            }
        }
    • 사용자 본인이 등록한 제품만 조회하는 기능의 API라 가정
      • Filter에서 인증 처리되어 넘어온 User 객체를 사용하면 API 요청을 한 해당 사용자가 등록한 제품만 조회 가능
/api/products
profile
전 체리 알러지가 있어요!

0개의 댓글