본문 바로가기
study

[JSCODE] 내 정보 조회 기능

by 당코 2023. 5. 27.

앞서 구현한 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에 대해서 직접 인증이 필요한 기능들에 접목시켜 보고 활용을 하다 보니 이론에서 뿐만 아니라 실질적으로 어떻게 프로그램 내에서 작동하는지 이해할 수 있었다. 직접 코드를 구현한 것은 많지 않지만 자세히 분석하면서 사용해 보니 많은 것을 배울 수 있었다. 하지만 좀 더 개선할 부분들이 있기 때문에 좀 더 효율적으로 코드를 리팩토링 할 수 있도록 고민해 봐야겠다.