본문 바로가기
Programming/Java * Spring

[SpringBoot] JWT(Json Web Token) 활용한 인증 처리

by 고막고막 2023. 4. 15.

담당 기능에서 외부 시스템과의 연동을 위해 JWT(Json Web Token)을 활용한 인증 처리가 필요했다. JWT는 자바 뿐만 아니라 .Net, C, C++, Go, JavaScript 등 거의 대부분의 프로그램 언어를 지원하는 인터넷 표준 인증 방식이다. 토큰 구성은 크게 Header / Payload / Signature 이며, 연동 시스템에서 요구한 명세는 아래와 같았다.

 

Header

- type : 말그대로 토큰 타입이 "JWT" 라는 의미

- alg : 알고리즘은 HMAC SHA-256 을 사용하였으며, 파라미터는 밸류는 "HS256". 알고리즘 타입별 상세 정보는 아래 RFC 공식 문서를 참고하는 것이 좋다.

https://www.rfc-editor.org/rfc/rfc7518#section-3.1

 

RFC 7518: JSON Web Algorithms (JWA)

 

www.rfc-editor.org

 

Payload

-  토큰을 식별할 수 있는 여러 properties 들을 정의할 수 있다. 나의 경우에는 사전 협의된대로 시스템 ID, 회사 ID, 사용자 ID 등을 담았다. 생성된 토큰을 디코딩 하면 이 정보들이 그대로 보이기 때문에 비밀번호 등의 민감정보는 넣지 않아야 한다.

- iat : UNIX Time 으로 타임스탬프를 만들었다. 

https://www.epochconverter.com/

 

Epoch Converter

Convert Unix Timestamps (and many other date formats) to regular dates.

www.epochconverter.com

 

Signature

- 서명에 사용될 암호화된 시크릿 키를 담아준다.

 

이제 자바 코드로 구현을 해보자.

먼저 io.jsonwebtoken 의존성을 추가해준다. 아래와 같이 api, jackson, impl 세개 모두 해줘야한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
cs

 

실제 토큰 생성하는 부분.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.util.Calendar;
 
private String buildToken(String appId, String clientId, String secretKey) {
    HashMap<String, Object> headers = new HashMap<>();
    headers.put("type""JWT");
    headers.put("alg""HS256");
 
    HashMap<String, Object> payload = new HashMap<>();
    payload.put("type""app");
    payload.put("app_id", appId);
    payload.put("client_id", clientId);
    payload.put("lat", Calendar.getInstance().getTimeInMillis() / 1000); // UNIX TimeStamp
    payload.put("company"this.getCompanyCode());
    payload.put("user"this.getGEmpCode());
 
    return Jwts.builder()
        .setHeader(headers)
        .setClaims(payload)
        .signWith(Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)))
        .compact();
}
cs

 

첨에 로컬에서 실행하려고 하니 java.lang.NoClassDefFoundError 가 발생했었다. 이는 컴파일 시점에는 아무 이상이 없으나 런타임 시점에는 JVM 해당 클래스 파일을 찾지 못해 발생하는 오류인데,

Springboot 멀티모듈 환경에서 개발을 하다보니 내가 작업 중인 모듈에만 해당 io.jsonwebtoken jar 를 참조했을 때는, boot로 구동을 하면서 하위 모듈에 걸려있는 jar를 읽어들이지 못한 것으로 보인다.

따라서 boot가 포함되어 있는 메인 모듈에도 동일하게 필요한 참조를 걸어주어 해결하였다.

 

결과

이렇게 생성된 토큰은 jwt.io 에서 디코딩해줘서 쉽게 검증할 수 있다!

https://jwt.io/

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io