발생한 문제

 

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);
	}

+ Recent posts