Hansel

코드로 JWT 생성 살펴보기 본문

프로젝트/과정

코드로 JWT 생성 살펴보기

핑슬 2022. 4. 30. 20:46

현재 DB엔 회원가입한 유저 튜플들이 존재한다.

 

이제 유저가 username(아이디)와 password를 가지고 로그인 요청을 하면

서버에서 그 credentials을 받아서 인증 처리를 하고 인증이 완료 되면 JWT를 생성하여 유저에게 준다.

 

그 다음 요청부터 유저는 JWT를 서버에 보내 JWT 토큰 인증 처리 절차를 밟으면 된다.

 

테스트용 로그인 메서드이다.

유저의 ID와 PWD를 담은 UserRequest Json 데이터를 받아 해당 데이터를 검증하고 JWT를 반환하는 역할을 한다.

 

AuthenticationManager가 무엇인지는 이전에 설명한적이 있다.

스프링 시큐리티의 동작 방식은 다음과 같았다.

- 유저의 요청(Credentials)

- Authentication Manager가 credential에 적합한 provider로 위임

- UserDetailsService에서 해당 유저 찾고 검증

- Principal 반환

 

그럼 파라미터로 넘기는 값이 유저의 Credential인걸 금방 알 수 있다.

그럼 UsernamePasswordAuthenticationToken은 무엇일까?

 

힌트는 AuthenticationManager의 파라미터로 들어간다.

우선 기본적인 스프링 시큐리티 순서에 따라 잘 작동된다.

Postman으로 보낸 데이터가 인증에 문제가 없으니 잘 통과되었다.

 

final PrincipalDetails userDetails = (PrincipalDetails) principalDetailsService.loadUserByUsername(userRequest.getUsername());

final String jwt = jwtUtil.generateToken(userDetails);

return ResponseEntity.ok(new UserResponse(jwt));

그럼 이제 이 부분을 살펴보자

 

Principal은 이미 잘 알고있으니 넘어가고

jwtUtil에서 호출하는 generateToken이 무엇인이 살펴보자

 

jwtUtil은 직접 작성해야하는 클래스이다.

jjwt 라이브러리를 이용하여 적절히 jwt 토큰을 만들고, 검증하고, 삭제하는 일을 하도록 구현하면 된다.

우선 generateToken은 UserDetails(Principal)을 받아 그 정보와 claim을 createToken으로 넘겼다.

파라미터로 넘긴것들에 대한 얘기는 조금 뒤에 하고 우선 createToken을 먼저 살펴보자

 

그럼 중요한 것은 모두 createToken에 있다.

여기선 jjwt 라이브러리를 이용해 jwt토큰을 만들것이다.

 

Jwts는 jwt 객체를 생성할 팩토리 클래스이며 이를 통해 쉽게 jwt를 생성할 수 있다.

또한 Jwts의 빌더를 통해 헤더, 페이로드, 시그니쳐를 쉽게 구성할 수 있다.

필드와 메서드만 봐도 "아 JWT를 만드는데 쓰겠구나" 싶다.

이 빌더의 setClaim, setSubject, setIssuedAt 등의 메서드를 연달아 호출하는데 각 메서드가 어떤 역할을 하는지 알아보자.

 

setClaim
Sets the JWT payload to be a JSON Claims instance populated by the specified name/value pairs.
If you do not want the JWT body to be JSON and instead want it to be a plaintext string,
use the setPayload(String) method instead.

주석으로 적혀있는 설명이다. 우리가 빈 해쉬맵 claim을 createToken의 파라미터로 보냈는데 위의 설명과 연관이 있다.

우리가 만들어서 보낸 클레임은 단순히 JWT 페이로드의 틀이라고 보면 된다.

페이로드 형식이 JSON이길 원하면 위와 같이 해쉬맵<String : Object>을 만들어 setClaim을 호출하면 되고 그냥 단순한 텍스트이길 원한다면 setPayload를 호출하면 된다.

 

setSubject

주로 식별의 대상이 되는 값을 사용한다.

여기서는 유저의 ID를 사용했다.

 

고유한 값을 사용하는게 좋은데 ID나 email 등 원하는 값을 사용하면 된다.

 

setIssuedAt & setExpiration

얘넨 메서드 이름만 봐도 알겠다. 패스

 

SignWith
더보기

Signs the constructed JWT using the specified algorithm with the specified key, producing a JWS.

명시된 알고리즘과 키를 사용해 Signature를 생성하는 메서드이다.

 

Compact
Actually builds the JWT and serializes it to a compact

모든 설정 작업이 완료된 후 Compact를 이용해 JWT 토큰을 만든다!

 

이렇게 jjwt 라이브러리를 이용해 JWT 토큰을 만들고 반환하는 과정을 살펴보았다.

 

이제 인증 과정을 살펴보러가자