java에서 jwt payload를 가져오는 방법에대해 정리하보고자 한다.
JWT 개념
JWT(Json Web Token)란 Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token 이다.
JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식 으로 정보를 안전하게 전달한다.
주로 회원 인증이나 정보 전달에 사용된다
intelliJ
maven
java 8
지금까지 JWT안에 payload를 가져올려면 public key나 private key가 있어야하는줄 알았는데
아래 사이트에서 바로 내용을 확인 할 수 있는것을 보고 key가 필요없다는걸 알게 되었다....
maven 프로젝트에서 사용한 dependency
는 아래와 같다.
...
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.16.0</version>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.10</version>
</dependency>
...
간단하게 java-jwt
를 사용하여 JWT
의 내용을 확인 할 수 있다.
DecodedJWT decodedJWT = JWT.decode({jwt_token});
System.out.println(decodedJWT.getClaims().toString());
여기서 Token은 헤더, 페이로드, 서명을 점으로 구분하는 구조로 되어있다.
DecodedJWT
인터페이스에는 Payload
와 Header
가 상속되어있어
getAlgorithm
로 알고리즘을 확인 할 수 있고 getExpiresAt
로 Token의 만료시간을 체크 할 수 있다.
...
try{
if(decodedJWT.getExpiresAt().before(new Date())){
throw new JWTVerificationException("The Token has expired on "+decodedJWT.getExpiresAt());
}
}catch(JWTVerificationException e){
System.out.println(e.getMessage());
}
...
JWT가 넘어오기전에 payload가 암호화되어 넘어오는 경우가 있다.
이렇게 암호화된 데이터는 4개의 점으로 구분되어 있고 당연히 암호화를 풀려면 복호화를 할 수 있는 private key
가 필요하다.
암호화된 JWT는 nimbus-jose-jwt
를 사용하여 payload를 복호화 해준다.
...
PrivateKey privateKey = getPrivateKey(filePath);
EncryptedJWT jwt = EncryptedJWT.parse({token});
//null 출력됨, decrypt를 해줘야 payload가 보임
System.out.println(jwt.getPayload());
//privateKey를 가지고 RSADecrypter객체 생성
RSADecrypter decrypter = new RSADecrypter(privateKey);
//jwt 복호화
jwt.decrypt(decrypter);
//payload에 데이터 출력
System.out.println(jwt.getPayload());
...
public static String decrypt(String cipherText, PrivateKey privateKey)
throws IOException, GeneralSecurityException {
byte[] decodedCipherText = cipherText.getBytes();
System.out.println("Decoded Cipher text == " + decodedCipherText.toString());
OAEPParameterSpec oaepParams = new OAEPParameterSpec(
"SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// cipher.init(Cipher.DECRYPT_MODE, privateKey);
System.out.println("algo " + cipher.getAlgorithm());
System.out.println("cipherText == " + cipherText);
return new String(cipher.doFinal(decodedCipherText), "UTF-8");
}
public static RSAPrivateKey getPrivateKeyFromString(String key) throws IOException, GeneralSecurityException {
String privateKeyPEM = key;
// Remove the first and last lines
privateKeyPEM = privateKeyPEM.replace("-----BEGIN RSA PRIVATE KEY-----", "");
privateKeyPEM = privateKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
privateKeyPEM = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----", "");
privateKeyPEM = privateKeyPEM.replace("-----END PRIVATE KEY-----", "");
System.out.println("privatekey pem after removal == " + privateKeyPEM);
byte[] encoded = java.util.Base64.getDecoder().decode(privateKeyPEM); // for util base64
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
System.out.println("RSA Private Key after encoded: " + privKey);
return privKey;
}
public static RSAPrivateKey getPrivateKey(String filename) throws IOException, GeneralSecurityException {
String privateKeyPEM = getKey(filename);
System.out.println("PrivateKeyPem == " + privateKeyPEM);
return getPrivateKeyFromString(privateKeyPEM);
}
static 메서드들은 privateKey file을 PrivateKey객체
로 만들어주는 메서드다.
[참고]
'Backend > JAVA' 카테고리의 다른 글
객체지향 5원칙 (SOLID) (0) | 2021.07.28 |
---|---|
객체지향 프로그래밍(OOP) (0) | 2021.07.27 |
[Tibero/Geometry 에러 처리] Data is too long for the column 에러/ tbClob/tbBlob 처리 방법(feat. GIS) (0) | 2021.05.13 |
[JAVA] Null/NaN/공백/문자열 처리 (0) | 2021.05.06 |
JAVA / JVM / JDK / JRE에 대해서 (0) | 2021.05.04 |