JJWT簡介(翻譯)

saka發表於2017-11-09

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提供了惟一的識別符號,如果應用程式
使用多個發行者,必須在值之間避免衝突,
由不同的發行商製作。

相關文章