Framework/Spring

[SpringSecurity] JWT 정보를 이용해 Controller에서 현재 로그인한 사용자의 정보 추출하기

MINGYUM 2023. 7. 9. 14:41

JWT로 로그인한 경우에 사용자의 정보를 가져와 Controller에서 사용해야하는 상황이 있다.

JWT 토큰을 생성하는 코드에서 Claims 에 넣은 정보를 현재 토큰에서 추출하는 방법으로 구현할 수 있는데, 이를 코드로 정리해보려 한다.

내가 만든 서비스에서는 사용자가 이메일과 패스워드를 입력하여 로그인하는 방식으로 구현되어있다. 사용자의 이메일을 JWT 에서 추출해 현재 로그인된 사용자 객체 Member을 가져오는 예제를 보여주도록 하겠다.

JwtUtil createToken 메소드

    public static String createToken(String mail, String key, long expireTimeMs) {
        Claims claims = Jwts.claims();
        claims.put("mail", mail);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + expireTimeMs))
                .signWith(SignatureAlgorithm.HS256, key)
                .compact();
    }

Claimsmail이라는 이름으로 사용자의 메일 주소 정보를 넣었다.

이는 실제로 로그인 시 사용자의 메일을 기반으로 토큰이 생성되기 때문에 JWT 에는 사용자의 메일 주소가 들어있음을 알 수 있다.

LoginService

   public String login(LoginDTO loginDTO) {
        Member member = memberRepository.findByMail(loginDTO.getMail())
                .orElseThrow(() -> new AppException(ErrorCode.MEMBER_NOT_FOUND));

        if (bCryptPasswordEncoder.matches(loginDTO.getPassword(), member.getPassword())) {
            String token = JwtTokenUtil.createToken(member.getMail(), key, expireTimeMs);
            return token;
        } else {
            throw new AppException(ErrorCode.INVALID_PASSWORD);
        }
    }

MemberController

    @GetMapping("/get-current-member")
    public Long getCurrentMember(Authentication authentication){
        log.info("authentication.getName() : " + authentication.getName());
        Member member = memberService.getMember(authentication.getName());
        return member.getId();
    }

MemberController에 위와 같이 현재 로그인된 사용자 정보를 가져오는 메소드를 작성하였다. 파라미터에는 Authentication 을 가져와, SecurityContextHolder에게 자동으로 Authentication 객체를 파라미터로 설정하도록 하였다.

authentication.getName()을 실행하면 초기에 Claims에 넣었던 사용자의 메일이 반환된다.

MemberService

  public Member getMember(String mail) {
        Member member = memberRepository.findByMail(mail)
                .orElseThrow(() -> new AppException(ErrorCode.MEMBER_NOT_FOUND));
        return member;
    }

getMember 메소드는 서비스단에서 구현하였는데, Repository에서 Mail 필드가 일치하는 DB의 튜플을 가져오도록 하였다.