발생한 문제
1. 헤더에 토큰을 유무를 확인하기 위한 문제
2. JWT토큰이 어느 사용자인지 확인하는 코드가 중복으로 발생
1. 에 대한 문제 해결 - Filter
1번 문제는 아주 간단하게 해결할 수 있었습니다.
@WebFilter(urlPatterns = "/user/*")
public class UserApiFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String authorization = httpServletRequest.getHeader("authorization");
if (authorization == null) {
throw new IllegalAccessError();
} else {
chain.doFilter(request, response);
}
}
}
Filter를 사용한 이유

그림과 같이 요청이 들어온다면 우선적으로 필터를 거치게 됩니다. 인증/인가되지 않는(JWT 토큰이 없는) 사용자는 Spring Context안으로 진입하지 못하게 막는 것을 위해 선택하였습니다.
2. 에 대한 문제 해결 - AOP
2번이 가장 많은 시간을 들여 고민을 하게되었습니다. 구상한 시나리오는 클라이언트로부터 데이터 요청이 들어오면 서버는 토큰의 유무를 확인하고 토큰안에 있는 유저정보를 통해 유저의 데이터를 전달하는 방식입니다.
@PostMapping("/quote/save")
public ResponseEntity savetUserQuote(@RequestBody QuoteDTO quoteDTO, HttpServletRequest httpServletRequest) {
// jwt안에 있는 유저정보를 확인하기 위한 로직
String authorization = httpServletRequest.getHeader("authorization");
String username = jwtLoginToken.getUsername(authorization);
// 비지니스 로직
UserEntity userinfo = userApiService.getUserApi(username);
userQuoteService.quoteInsert(quoteDTO, null);
return new ResponseEntity(HttpStatus.OK);
}
@PostMapping("/quote/update")
public ResponseEntity updateUserQuote(@RequestBody QuoteDTO quoteDTO, HttpServletRequest httpServletRequest) {
// jwt안에 있는 유저정보를 확인하기 위한 로직
String authorization = httpServletRequest.getHeader("authorization");
String username = jwtLoginToken.getUsername(authorization);
// 비지니스 로직
userQuoteService.quoteUpdate(quoteDTO);
return new ResponseEntity(HttpStatus.OK);
}
// ...등등
AOP기술을 선택한 이유
1. 유저 정보를 확인하는 로직과 비지니스 로직을 구분짖기 위해
2. 코드 중복을 피하기 위해
3. 나중을 위해 확장성을 열어두기 위해
코드
custom 어노테이션을 사용했습니다.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @ interface TokenValidator {
}
@Autowired
private AuthenticationJwtToken authenticationJwtToken;
Logger logger = LoggerFactory.getLogger(UserAop.class);
@Pointcut("execution(* com.todo.list.controller.UserController..*(.., @TokenValidator (*), ..))")
public void cut() {
}
@Around(value = "cut()")
public Object test(ProceedingJoinPoint joinPoint) throws Throwable {
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
String token = httpServletRequest.getHeader("authorization");
authenticationJwtToken.getUserTokenDTO(token);
Object[] args = Arrays.stream(joinPoint.getArgs()).map(data -> {
if (data instanceof UserTokenDTO) {
data = authenticationJwtToken.getUserTokenDTO(token);
}
return data;
}).toArray();
return joinPoint.proceed(args);
}'문제해결 및 코드 만들기' 카테고리의 다른 글
| 서버 시작 전 더미 데이터 넣는 경우 발생 했던 문제점 (0) | 2022.05.11 |
|---|---|
| 스프링 MultipartFile을 사용할 때 나타난 오류들 (0) | 2022.05.02 |
| 2022-01-20(개인 프로젝트) 시간 단축 (0) | 2022.01.20 |
| 2021-12-13 비밀번호 만들기 (0) | 2021.12.13 |
| 2021-10-12 (회고록) 체스 게임 객체지향적 설계연습 (0) | 2021.10.12 |