Java JWT: JSON Web Token for Java and Android
JJWT的是在JVM上創建和驗證JSON Web Token(JWTs)的庫。
JJWT是基于JWT、JWS、JWE、JWK和JWA RFC規范的Java實現。
這個庫是由Okta的Les Hazlewood創建的,現在由一個貢獻者社區維護。
什么是JSON Web Token
JWT是一種在兩方之間傳輸信息的方法。
在JWT的主體中編碼的信息被稱為claims。JWT的擴展形式是JSON格式,因此每個claim都是JSON對象中的一個鍵。
JWTs可以加密簽名(使它成為JWS)或加密(使它成為JWE)。
這為JWTs增強了可驗證性。例如,接收者可以確定JWT沒有通過驗證簽名來篡改。
所生成JWT的結果是有三個部分的字符串,每個部分由"."分隔。
例如:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.ipevRNuRP6HflG8cFKnmUPtypruRC4fb1DWtoLL62SY
每一節都是base 64編碼的。
第一部分是header,必須指定用于簽署JWT的算法。
eyJhbGciOiJIUzI1NiJ9
第二部分是body。本節包含了JWT編碼的所有聲明。
eyJzdWIiOiJKb2UifQ
最后一部分是signature。它通過在頭文件中指定的算法通過header和body的組合來計算。
ipevRNuRP6HflG8cFKnmUPtypruRC4fb1DWtoLL62SY
如果你通過一個基本的64解碼器傳遞前兩個部分,你將得到:
header
{
"alg": "HS256"
}
body
{
"sub": "Joe"
}
在這種情況下,我們得到的信息是使用sha - 256算法的HMAC來簽署JWT。而且,body有一個claim sub與value Joe。
Registered Claims 包含一些標準的claims,sub就是其中的一個(subject)。
要計算簽名,你必須知道簽名的sercrect。
安裝
Maven:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
Gradle:
dependencies {
compile 'io.jsonwebtoken:jjwt:0.9.0'
}
Note:JJWt依賴了 Jackson 2.x。
假如你依賴了jackson的老版本,你必須更新項目中的版本到新版本,否則會沖突。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.9</version>
</dependency>
快速使用
先看一個簡單的例子:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;
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 = MacProvider.generateKey();
String compactJws = Jwts.builder()
.setSubject("Joe")
.signWith(SignatureAlgorithm.HS512, key)
.compact();
在上邊的例子中下,我們構建了一個JWT,該JWT將將注冊的claim的sub(subject)設置為Joe,使用sha - 512算法在HMAC上注冊JWT。最后,我們將它轉換成字符串形式。
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJKb2UifQ.yiV1GWDrQyCeoOswYTf_xvlgsnaVVYJM0mU6rkmRBf2T1MBl3Xh2kZii0Q9BdX5-G0j25Qv2WF4lA6jPl5GKuA
下面來驗證一下jwt:
assert Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws).getBody().getSubject().equals("Joe");
這里有兩個時間。之前的密鑰被用來驗證JWT的簽名。如果未能驗證JWT,則拋出一個簽名異常。假設JWT已被驗證,我們將解析claim并斷言該sub被設置為Joe。
但如果簽名驗證失敗了怎么辦?可以捕獲簽名異常并做出相應的反應:
try {
Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws);
//OK, we can trust this JWT
} catch (SignatureException e) {
//don't trust the JWT!
}
支持的特性
兼容的規范
- 創建和解析明文壓縮JWTs
- 創建、解析和驗證所有標準JWS算法的數字簽名JWTs(又稱JWSs):
- HS256: HMAC using SHA-256
- HS384: HMAC using SHA-384
- HS512: HMAC using SHA-512
- RS256: RSASSA-PKCS-v1_5 using SHA-256
- RS384: RSASSA-PKCS-v1_5 using SHA-384
- RS512: RSASSA-PKCS-v1_5 using SHA-512
- PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256
- PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384
- PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512
- ES256: ECDSA using P-256 and SHA-256
- ES384: ECDSA using P-384 and SHA-384
- ES512: ECDSA using P-521 and SHA-512
增強的規范
- body壓縮。如果JWT體大,可以使用壓縮解碼器來壓縮它。最重要的是,JJWT庫將自動解壓并解析JWT,而不需要額外的編碼。
String compactJws = Jwts.builder()
.setSubject("Joe")
.compressWith(CompressionCodecs.DEFLATE)
.signWith(SignatureAlgorithm.HS512, key)
.compact();
如果檢查Jws的header部分,它就會對這個進行解碼:
{
"alg": "HS512",
"zip": "DEF"
}
JJWT自動檢測到壓縮是通過檢查頭來使用的,并且在解析時將自動解壓。對于解壓縮,不需要額外的編碼。
- 要求claims。在解析時,您可以指定某些斷言必須存在并設置為某個值。
try {
Jws<Claims> claims = Jwts.parser()
.requireSubject("Joe")
.require("hasMotorcycle", true)
.setSigningKey(key)
.parseClaimsJws(compactJws);
} catch (MissingClaimException e) {
// we get here if the required claim is not present
} catch (IncorrectClaimException e) {
// we get here if the required claim has the wrong value
}
Registered Claim
所有的claim是可選的,并且是大小寫敏感的。
1. "iss" (Issuer) Claim
"iss" (issuer)是簽發該證書的負責人。
2. "sub" (Subject) Claim
"sub" (Subject)是主體。
3. "aud" (Audience) Claim
"aud" (Audience) Claim是指jwt的接受者,假如aud沒有發現,則解析jwt時會拋出異常
4. "exp" (Expiration Time) Claim
"exp" (Expiration Time)指的是過期時間,假如超過過期時間,則會拋出異常
5. "nbf" (Not Before) Claim
"nbf" (Not Before) Claim指的是開始日期,claim要求當前日期/時間必須在以后或等于
在“nbf”聲明中列出的日期/時間
6. "iat" (Issued At) Claim
"iat" (Issued At) Claim是指jwt的發行時間
7. "jti" (JWT ID) Claim
"jti" (JWT ID) Claim為JWT提供了惟一的標識符,如果應用程序
使用多個發行者,必須在值之間避免沖突,
由不同的發行商制作。