1. Filter란?
1. 정의

- Client로 부터 오는 요청과 응답에 대한 최초/최종 단계의 위치이며, 요청과 응답에 대한 정보를 변경하거나 부가적인 기능을 추가할 수 있다.
- 주로 로깅 및 보안처리에 활용
- 인증, 인가와 관련된 로직도 처리
- 비즈니스 로직과 보안적인 로직을 분리하여 관리할 수 있다는 장점이 있다.
2. Filter chain

- Filter는 한 개만 존재하는 것이 아니라 여러개의 chain형식으로 묶여서 처리 가능
2. 사용예시
1. Logging
@Slf4j(topic = "LoggingFilter")
@Component
@Order(1)
public class LoggingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String url = httpServletRequest.getRequestURI();
log.info(url);
chain.doFilter(request, response);
log.info("비즈니스 로직 완료");
}
}
@Order(1)
: 필터의 순서를 지정
chain.doFilter(request, response);
: 다음 Filter로 이동
log.info("비즈니스 로직 완료");
: 작업이 다 완료된 후 Client에 응답 전 로그가 작성된 것을 확인
2. 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"))
) {
chain.doFilter(request, response);
} else {
String tokenValue = jwtUtil.getTokenFromRequest(httpServletRequest);
if (StringUtils.hasText(tokenValue)) {
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);
} else {
throw new IllegalArgumentException("Not Found Token");
}
}
}
}
- httpServletRequest.getRequestURI() 요청 URL을 가져와서 구분합니다. (인가)
- URL 인증 처리 진행
- jwtUtil.getTokenFromRequest(httpServletRequest);
- httpServletRequest
에서 Cookie 목록을 가져와 JWT가 저장된 Cookie를 찾는다.
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");
} catch (UnsupportedEncodingException e) {
return null;
}
}
}
}
return null;
}
3. Controller에서 처리
@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:/";
}
}
출처
내일배움캠프 Spring Master