JWT(JSON Web Token)는
사용자 인증 정보를 담아 서버와 클라이언트 간에 안전하게 전달하기 위한 토큰 기반 인증 방식이다.
핵심 목적:
JWT는 3개의 문자열로 구성된다.
Header.Payload.Signature
예시:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJ1c2VySWQiOiJoYW51bCJ9
.
abc123signature
토큰의 타입과 서명 알고리즘을 명시
{
"alg": "HS256",
"typ": "JWT"
}
실제 데이터
{
"userId": "hanul"
}
⚠️ 민감한 정보는 절대 넣으면 안됨 (평문 노출됨)
위조 방지를 위한 서명
HMACSHA256(
base64Url(Header) + "." + base64Url(Payload),
secretKey
)
+, /, = → URL, HTTP에서 문제 발생+ → -/ → _= 제거👉 JWT는 HTTP 환경에서 안전하게 사용하기 위해 Base64Url 사용
1. 로그인 요청
2. 서버 → JWT 발급
3. 클라이언트 → 토큰 저장
4. 요청 시 JWT 포함
5. 서버 → 토큰 검증
Base64UrlUtil.java
JwtSignatureUtil.java
JwtUtil.java
JwtValidator.java
Main.java
import java.util.Base64;
/* Base64Url 인코딩 */
public class Base64UrlUtil {
public static String encode(byte[] data) {
return Base64.getUrlEncoder().withoutPadding().encodeToString(data);
}
public static String encode(String data) {
return Base64.getUrlEncoder().withoutPadding().encodeToString(data.getBytes());
}
public static String decode(String data) {
return new String(Base64.getUrlDecoder().decode(data));
}
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class JwtSignatureUtil {
public static String createSignature(String data, String secret) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
mac.init(key);
byte[] rawHmac = mac.doFinal(data.getBytes());
return Base64UrlUtil.encode(rawHmac);
}
}
public class JwtUtil {
private static final String SECRET = "my-secret-key";
public static String createToken(String userId) throws Exception {
String header = Base64UrlUtil.encode("{\"alg\":\"HS256\",\"typ\":\"JWT\"}");
String payload = Base64UrlUtil.encode("{\"userId\":\"" + userId + "\"}");
String data = header + "." + payload;
String signature = JwtSignatureUtil.createSignature(data, SECRET);
return data + "." + signature;
}
}
public class JwtValidator {
private static final String SECRET = "my-secret-key";
public static boolean validate(String token) throws Exception {
String[] parts = token.split("\\.");
if (parts.length != 3) return false;
String header = parts[0];
String payload = parts[1];
String signature = parts[2];
String data = header + "." + payload;
String newSignature = JwtSignatureUtil.createSignature(data, SECRET);
return signature.equals(newSignature); // jwt 서명 생성 결과 비교
}
}
public class Main {
public static void main(String[] args) throws Exception {
String token = JwtUtil.createToken("Hanul");
System.out.println("JWT: " + token);
boolean valid = JwtValidator.validate(token);
System.out.println("검증 결과: " + valid);
// Payload 디코딩
String payload = Base64UrlUtil.decode(token.split("\\.")[1]);
System.out.println("Payload: " + payload);
}
}


이미지 출처: https://blog.algomaster.io/p/json-web-tokens