일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- java list 출력
- 항해99후기
- 인터프린터언어
- 컴파일
- java참조자료형
- 비전공자sqld
- sqld자격증합격
- java map
- 격파르타장점
- java list 저장
- 격파르타후기
- java set 저장
- javaJRE
- java set 출력
- javaJVM
- java알고리즘문제풀이
- 프로그래머스제일작은수
- java 자료구조 활용
- 작은수제거하기
- 격파르타비전공자
- 노베이스부트캠프
- java map 출력
- java알고리즘
- 항해15기
- java최솟값구하기
- 코딩부트캠프후기
- 프로그래머스
- 격파르타합격후기
- java map 저장
- java기본자료형
- Today
- Total
코딩과 결혼합니다
230705 - Spring 필터 적용 코드 분석 본문
@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); // 다음 Filter 로 이동
//후처리
log.info("비즈니스 로직 완료");
}
}
@Slf4j 어노테이션을 사용하여 LoggingFilter 클래스에 대한 로깅 기능을 추가한다. 이 어노테이션은 lombok 프레임워크를 통해 코드에서 로깅을 쉽게 처리할 수 있도록 해준다.
@Order(1) 필터의 실행 순서를 지정.
doFilter 에서는 ServletRequset / ServletResponse를 받아올 수 있고, FilterChain 을 이용해 필터간의 이동이 가능하다.
//전처리 에서는 ServeltRequest를 HttpServletRequset로 캐스팅하여 요청의 URI를 얻고, log.info()를 사용하여 해당 URL을 로깅한다.
로깅? : 애플리케이션의 동작과 관련된 정보를 기록하는 것. 주로 디버깅, 모니터링, 오류 추적 등을 위해 사용된다.
-일반적으로 로그 메시지는 로그 레벨과 함께 기록되며, 로그 레벨에는 다음과 같은 종류가 있다.
- DEBUG: 디버깅 목적으로 사용되는 세부 수준의 로그입니다. 애플리케이션의 내부 상태와 변수 값을 추적하고 분석하는 데 사용됩니다.
- INFO: 정보성 로그로서, 애플리케이션의 주요 이벤트 및 상태 정보를 기록합니다. 예를 들어, 애플리케이션의 시작 또는 중지, 요청 처리 결과 등을 기록할 수 있습니다.
- WARN: 경고성 로그로서, 애플리케이션이 예상치 않은 동작을 했거나 잠재적인 문제 상황에 진입했을 때 기록합니다. 애플리케이션은 계속 작동하지만 주의해야 할 상황임을 알려줍니다.
- ERROR: 에러가 발생했을 때 기록하는 로그입니다. 예외 상황, 처리 불가능한 오류 또는 중대한 문제를 나타내며, 애플리케이션이 오작동하거나 중단될 수 있습니다.
LoggingFilter 클래스의 예제서는 log.info()를 사용하여 로그 메시지를 기록하고 있다. 이를 통해 애플리케이션의 요청
URL과 "비즈니스 로직 완료" 라는 메시지를 로깅한다. 이러한 로그는 애플리케이션의 동작을 추적하고, 요청 처리의 진행 상황 및 완료 여부를 확인하는데 도움을 준다.
전처리, 후처리 로깅을 수행하고 chain.doFilter() 메서드를 호출하여 다음 필터로 제어를 넘긴다.
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String url = httpServletRequest.getRequestURI();
받아온 메시지를 HttpServletRequest 형태로 만들어 httpServletRequest 안에 값을 저장한다.
다음, url 에 .getRequestURI() 메서드를 이용해 URI를 저장한다.
if (StringUtils.hasText(url) &&
(url.startsWith("/api/user") || url.startsWith("/css") || url.startsWith("/js"))
) {
// 회원가입, 로그인 관련 API 는 인증 필요없이 요청 진행
chain.doFilter(request, response); // 다음 Filter 로 이동
.hasText 로 url이 존재하는지 확인 후 url이 아래의 조건들을 만족한다면 바로 다음필터로 이동한다.
회원가입, 로그인 관련 API는 인증이 필요하지 않기 때문이다.
} else {
// 나머지 API 요청은 인증 처리 진행
// 토큰 확인
String tokenValue = jwtUtil.getTokenFromRequest(httpServletRequest);
그 외의 것들은 인증 처리를 진행 하는데 먼저 토큰을 확인한다.
jwt > 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;
}
필터는 DispatcherSvervlet보다 더 앞쪽에 위치하기 때문에 @CookieValue라는 어노테이션 사용할 수 없다. 그렇기 때문에 직 Cookie를 뽑아오는 메서드 구현하였다.
req.getCookies 로 여러 개가 담긴 Cooke들을 전부 배열로 가져온다.
다음 Cookies가 존재하면 그 쿠키들 중에서 이름이 AUTHORIZATION_HEADER 인지 아닌지 체크 후
맞다면 다지고 온다. + decode 까지 해서 return
만약 오류가 발생하거나 Cookie 가 없다면 null 반환
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");
}
토큰이 존재하면 .substringToken 을 하여 순수한 Token만 뽑아낸다.
토큰 검증 후에 Token에서 사용자 정보를 가져온다.
Token 이 넘어올 때에 해당유저가 있다는 보장이 없으므로 데이터베이스에 접근해서 해당유저가 있는지 체크한다.
request 객체를 Controller로 넘길 것이기 때문에 .setAttribute로 유저 객체를 넣어 사용가능하게 하였다.
끝나면 다음 필터로 이동한다.
'2세 > Spring' 카테고리의 다른 글
230707 - Spring @Controller와 @RestController 차이 (0) | 2023.07.07 |
---|---|
230706 - 테이블, entity 간의 연관 관계 (0) | 2023.07.06 |
Spring 회원 가입 구현과 에러 잔치^^ (0) | 2023.07.05 |
230704 - annotation 정리 (회원 가입 구현) (0) | 2023.07.04 |
230703 - Bean 수동 등록 (1) | 2023.07.03 |