앞서 구현한 Jwt를 사용하여 나의 정보를 반환하는 api를 구현해 보았다.
로그인을 할 때 받은 토큰을 파싱 하여 claim안에 있는 유저의 id를 꺼내어 작업을 수행하도록 했다.
//Controller
@GetMapping("/info")
public ResponseEntity<MemberResponse> Info(@RequestHeader("Authorization") String token) {
MemberResponse response = memberService.findMemberInfo(token.substring(7));
return ResponseEntity.ok(response);
}
서비스 계층에서 TokenProvider를 통해 Authentication 객체로 변환하고 사용자의 id를 가져와 DB에 접근하도록 만들었다.
//Service
public MemberResponse findMemberInfo(String token){
Authentication authentication = tokenProvider.getAuthentication(token);
Long id = Long.valueOf(authentication.getName());
Member member = memberRepository.findById(id).orElseThrow(NotFoundMemberException::new);
return MemberResponse.from(member);
}
내 정보를 가져올 때 다음과 같은 Jwt에 대한 예외를 처리를 해 주었다.
- Header에 JWT 토큰이 담겨있지 않다면 에러로 응답한다.
- Header에 담겨있는 JWT 토큰이 올바르지 않거나 조작되었다면 에러로 응답한다.
- Header에 담겨있는 JWT 토큰의 만료기간이 지났다면 에러로 응답한다.
public class JwtFilter extends OncePerRequestFilter {
...
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String jwt = resolveToken(request);
if(StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)){
Authentication authentication = tokenProvider.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request,response);
}
}
OncePerRequestFilter를 상속받은 JwtFilter에서 request에 대한 인증 정보가 있는지 검증하는 코드를 추가하여 filter 단계에서 검증할 수 있게 해 주었다.
public boolean validateToken(String token) {
try {
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
return true;
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
log.info("잘못된 JWT 서명입니다.");
throw new InvalidJwtSignatureException();
} catch (ExpiredJwtException e) {
log.info("만료된 JWT 토큰입니다.");
throw new ExpiredJwtTokenException();
} catch (UnsupportedJwtException e) {
log.info("지원되지 않는 JWT 토큰입니다.");
throw new UnsupportedJwtTokenException();
} catch (IllegalArgumentException e) {
log.info("JWT 토큰이 잘못되었습니다.");
throw new InvalidJwtTokenException();
}
}
여러 가지 예외에 대해서 각각의 예외를 throw 하도록 만들어 주었다.
어려웠던 점, 개선할 점
Jwt에 대해서 직접 인증이 필요한 기능들에 접목시켜 보고 활용을 하다 보니 이론에서 뿐만 아니라 실질적으로 어떻게 프로그램 내에서 작동하는지 이해할 수 있었다. 직접 코드를 구현한 것은 많지 않지만 자세히 분석하면서 사용해 보니 많은 것을 배울 수 있었다. 하지만 좀 더 개선할 부분들이 있기 때문에 좀 더 효율적으로 코드를 리팩토링 할 수 있도록 고민해 봐야겠다.
'study' 카테고리의 다른 글
[JSCODE] 프로젝트 스터디 회고 (0) | 2023.06.01 |
---|---|
[JSCODE] 1 : N 관계 (0) | 2023.05.31 |
[JSCODE] JWT를 이용한 로그인 구현 (2) | 2023.05.24 |
[JSCODE] 회원가입, 로그인 기능 추가 (0) | 2023.05.20 |
[JSCODE] Elastic Beanstalk을 통한 배포 (0) | 2023.05.17 |