JJWT는 JVM과 Android 위에서 JSON Web Tokens (JWTs)를 식별하고 생성하기 위한 라이브러리를 이해하고 사용하기 가장 간편하도록 하는데 초점을 맞췄습니다.
JJWT는 순수 Java 구현체로 생성되었으며 Apache 2.0 License를 따르는 오픈 소스입니다.
JWT는 간결하고 검증 가능한 형태로 두 당사자간에 정보를 전송하는 수단입니다.
JWT의 body에 인코딩된 정보들을 claim 이라고 합니다. JWT의 확장된 형태는 JSON 형식이므로 각각의 클레임은 JSON 객체의 키입니다.
JWT는 서명 또는 암호화 될 수 있습니다. 이는 JWT 사용자에게 강력한 검증 가능을 주게됩니다. 수신자는 서명을 확인하여 JWT가 조작되지 않았다는 것을 확인하기 때문에 높은 신뢰도를 가지고 있습니다.
서명된 JWT의 간별한 표현은 각각 .로 구분되는 세 부분으로 구성된 문자열입니다.
각 파트는 Base64 URL로 인코딩 되어있습니다.
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
// We need a signing key, so we'll create one just for this example. Usually
// the key would be read from your application configuration instead.
Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
String jws = Jwts.builder().setSubject("Joe").signWith(key).compact();
위의 코드를 설명하면 아래와 같다.
jws의 형태는 아래와 같다.
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
jwt를 식별하는 방법
assert Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jws).getBody().getSubject().equals("Joe");
여기서 parseClaimsJws 메소드를 잘 사용하고 있는지 주의해야된다. 만약에 잘못된 메소드를 사용할 경우 UnsupportedJwtException이 발생하게 된다.
jwt를 식별하면서 2가지 일이 발생한다.
JWT 식별 실패를 대비해서 try catch 문을 사용한다.
try {
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compactJws);
//OK, we can trust this JWT
} catch (JwtException e) {
//don't trust the JWT!
}
SignatureException의 부모는 JwtException이므로 위 catch문에 걸리게 된다.
서명된 JWT는 2가지 기능을 제공한다.
JWT 가 생성되는 방식
header
{
"alg": "HS256"
}
body
{
"sub": "Joe"
}
String header = '{"alg":"HS256"}'
String claims = '{"sub":"Joe"}'
String encodedHeader = base64URLEncode( header.getBytes("UTF-8") )
String encodedClaims = base64URLEncode( claims.getBytes("UTF-8") )
String concatenated = encodedHeader + '.' + encodedClaims
인코딩된 헤더와 클레임이 결합된 문자열을 HMAC-SHA-256 알고리즘을 사용해서 암호화한다.
Key key = getMySecretKey()
byte[] signature = hmacSha256( concatenated, key )
암호화된 문자열을 signature로 부른다. 이를 아까 인코딩된 header와 claim이 결합된 문자열과 합처서 jws를 만든다.
`String jws = concatenated + '.' + base64URLEncode( signature )`
jws문자열의 내용은 아래와 같다.
`eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60`
JJWT에서는 위와같은 과정을 알아서 자동으로 처리해준다. 위와같은 작업을 수동으로 할 경우 코드를 잘못 만들 수 있고 보안에 취약해질 수 있다.
공식 문서 참조