Spring

[Spring] Oauth 연동 - JWT 로그인 기능 구현하기

obin01 2025. 1. 21. 16:41

1. JWT

JWT란?

JSON Web Token은 JSON 객체로 정보를 안전하게 전송하는 자체적인 방법을 정의한 표준

  • OAuth는 Token을 이용한 인증방식을 말하는 것이고 JWT는 Token
  • JWT를 생성할 때 헤더와 페이로드 정보를 인코딩하고, 이들을 합친 문자열에 대해 비밀 키로 서명을 생성
  • 한번 발급된 token은 수정, 폐기가 불가하여 Access token, Refresh token 사용

1) JWT 라이브러리

📌 jjwt, java-jwt

jjwt : Java 기반의 경량 JWT 처리 라이브러리로, JWT 생성, 파싱, 서명, 그리고 검증을 지원

java-jwt : JWT 생성 및 검증뿐만 아니라 OAuth2, OpenID Connect(OIDC)와 같은 표준 프로토콜을 지원

 

2) JWT 암호화 방식

📌 대칭키, 비대칭키

대칭키 : 암호화 복호화 키가 같은 방식, HMAC 암호화 알고리즘, private key로  암호화 하기 때문에 private key가 있어야 복호화 가능

비대칭키 : 암호화 복호화 키가 다른 방식, RSA 암호화 알고리즘, private key로 암호화 하면 public key 로 복호화 가능 (반대로도 가능)

2. build.gradle

implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

 

3. JwtUtil

package oauth.core.util;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Collection;
import java.util.Date;

import org.springframework.security.core.GrantedAuthority;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;

public class JwtUtil {

	private final PrivateKey privateKey;
	private final PublicKey publicKey;
	private final long expirationTimeMs = 1000 * 60 * 60; // 1시간 (ms)

	public JwtUtil() {
		// 비대칭키 RS256 사용
		KeyPair keyPair = Jwts.SIG.RS256.keyPair().build();
		this.privateKey = keyPair.getPrivate();
		this.publicKey = keyPair.getPublic();
	}

	// JWT 토큰 생성
	public String generateToken(Authentication authentication) {
		return Jwts.builder()
	    		.subject(authentication.getName())
	    		.claim("user",authentication.getDetails())
	    		.issuedAt(new Date(System.currentTimeMillis()))
	    		.expiration(new Date(System.currentTimeMillis() + expirationTimeMs))
	    		.signWith(privateKey)
	    		.compact();
	}
    
	// JWT 토큰 검증
	public String validateToken(String token) {
		 
		try {
			Jws<Claims> jws = Jwts.parser()
						.verifyWith(publicKey)
						.build()
						.parseSignedClaims(token);
			return jws.getPayload().getSubject();
		} catch (JwtException e) {
			throw new IllegalArgumentException("Invalid JWT token", e);
		}
	}
}

📌 JwtUtil

expirationTimeMs : 토큰 만료시간 (ms)

Jwts.SIG.RS256.keyPair().build() : JWT의 비대칭키 RS256 암호화 방식 사용

📌 generateToken

Jwts.builder() : jwt 토큰 builder로 생성

subject(username) : 전달 받은 파라미터로 고유 ID 값을 설정

claim("role", role) : 전달 받은 파라미터에 고유 ID 이외의 값 설정

issuedAt(new Date(System.currentTimeMillis())) : 토큰 생성 시간
expiration(new Date(System.currentTimeMillis() + expirationTimeMs)) : 토큰 만료 시간
signWith(privateKey) : privateKey로 암호화
compact() : 압축 및 서명 메서드를 호출

📌 validateToken

Jwts.parser() : jwt 토큰 parser로 확인

verifyWith(publicKey) : publicKey 로 검증

parseSignedClaims(token) : 전달 받은 파라미터로 파싱하여 서명이 검증된 정보를 반환

jws.getPayload().getSubject() : payload에서 기존에 넣었던 subject를 추출

JwtException : 만료 되었거나 검증에 문제가 생길경우 예외처리

 

 

 

 

 

4. 발급후 토큰 확인

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