1. 程式人生 > >JWT(Json Web Token)框架 jjwt 教程

JWT(Json Web Token)框架 jjwt 教程

JSON Web Token(JWT)是一個非常輕巧的規範。這個規範允許我們使用JWT在使用者和伺服器之間傳遞安全可靠的資訊。和 Cookie-Session 的模式不同,JSON Web Token(JWT)使用 Token 替換了 SessionId 的資源訪問和狀態的保持。基於JWT的Token認證的方式有很多優點,本文將介紹 JJWT 的相關用法。

jwt是什麼?

JWTs是JSON物件的編碼表示。JSON物件由零或多個名稱/值對組成,其中名稱為字串,值為任意JSON值。JWT有助於在clear(例如在URL中)傳送這樣的資訊,可以被信任為不可讀(即加密的)、不可修改的(即簽名)和URL – safe(即Base64編碼的)。

jwt的組成

  • Header: 標題包含了令牌的元資料,並且在最小包含簽名和/或加密演算法的型別
  • Claims: Claims包含您想要簽署的任何資訊
  • JSON Web Signature (JWS): 在header中指定的使用該演算法的數字簽名和宣告

jwt 的認證過程

  1. 使用者登入系統;
  2. 服務端驗證,將認證資訊通過指定的演算法(例如HS256)進行加密,例如對使用者名稱和使用者所屬角色進行加密,加密私鑰是儲存在伺服器端的,將加密後的結果傳送給客戶端,加密的字串格式為三個"." 分隔的字串 Token,分別對應頭部、載荷與簽名,頭部和載荷都可以通過 base64 解碼出來,簽名部分不可以;
  3. 客戶端拿到返回的 Token,儲存到 local storage 或本地資料庫;
  4. 下次客戶端再次發起請求,將 Token 附加到 header 中;
  5. 服務端獲取 header 中的 Token ,通過相同的演算法對 Token 中的使用者名稱和所屬角色進行相同的加密驗證,如果驗證結果相同,則說明這個請求是正常的,沒有被篡改。這個過程可以完全不涉及到查詢 Redis 或其他儲存;

JWT 安全性

  • 有很多庫可以幫助您建立和驗證JWT,但是當使用JWT時,仍然可以做一些事情來限制您的安全風險。在您信任JWT中的任何資訊之前,請始終驗證簽名。這應該是給定的。換句話說,如果您正在傳遞一個祕密簽名金鑰到驗證簽名的方法,並且簽名演算法被設定為“none”,那麼它應該失敗驗證。
  • 確保簽名的祕密簽名,用於計算和驗證簽名。祕密簽名金鑰只能由發行者和消費者訪問,不能在這兩方之外訪問。
  • 不要在JWT中包含任何敏感資料。這些令牌通常是用來防止操作(未加密)的,因此索賠中的資料可以很容易地解碼和讀取。
  • 如果您擔心重播攻擊,包括一個nonce(jti索賠)、過期時間(exp索賠)和建立時間(iat索賠)。這些在JWT規範中定義得很好。

jwt的優點

  • 使用 json 作為資料傳輸,有廣泛的通用型,並且體積小,便於傳輸;
  • 不需要在伺服器端儲存相關資訊;
  • jwt 載荷部分可以儲存業務相關的資訊(非敏感的),例如使用者資訊、角色等;

JJWT

JJWT是一個提供端到端的JWT建立和驗證的Java庫。永遠免費和開源(Apache License,版本2.0),JJWT很容易使用和理解。它被設計成一個以建築為中心的流暢介面,隱藏了它的大部分複雜性。

  • JJWT的目標是最容易使用和理解用於在JVM上建立和驗證JSON Web令牌(JWTs)的庫。
  • JJWT是基於JWT、JWS、JWE、JWK和JWA RFC規範的Java實現。
  • JJWT還添加了一些不屬於規範的便利擴充套件,比如JWT壓縮和索賠強制。

JJWT 規範相容

  • 建立和解析明文壓縮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

下面我們根據 https://github.com/jwtk/jjwt 上的demo,來介紹下 JJWT 的用法。

jjwt 安裝

jjwt 提供了 Maven 和 Gradle 兩種構建方式,Maven 配置如下即可使用 JJWT。

1

2

3

4

5

<dependency>

    <groupId>io.jsonwebtoken</groupId>

    <artifactId>jjwt</artifactId>

    <version>0.9.0</version>

</dependency>

Gradle 使用方式如下:

1

2

3

dependencies {

    compile 'io.jsonwebtoken:jjwt:0.9.0'

}

注意:JJWT依賴於Jackson 2.x. 如果您已經在您的應用程式中使用了舊版本的 Jackson 請升級相關配置。

建立簽名金鑰

1

2

3

4

5

6

7

8

9

10

11

import io.jsonwebtoken.Jwts;

import io.jsonwebtoken.SignatureAlgorithm;

import io.jsonwebtoken.impl.crypto.MacProvider;

import java.security.Key;

// 建立簽名金鑰,通常將從應用程式配置中讀取。

// 業餘草:www.xttblog.com

Key key = MacProvider.generateKey();

String compactJws = Jwts.builder()

  .setSubject("Joe")

  .signWith(SignatureAlgorithm.HS512, key)

  .compact();

驗證JWT

1

assert Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws).getBody().getSubject().equals("Joe");

SignatureException 異常

簽名驗證失敗呢?你可以捕捉SignatureException並作出相應的反應。

1

2

3

4

5

6

7

try {

    Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws);

    //OK, we can trust this JWT

    //業餘草:www.xttblog.com

catch (SignatureException e) {

    //don't trust the JWT!

}

壓縮簽名

1

2

3

4

5

String compactJws =  Jwts.builder()

    .setSubject("Joe")

    .compressWith(CompressionCodecs.DEFLATE)

    .signWith(SignatureAlgorithm.HS512, key)

    .compact();

解析時,可以指定某些宣告必須存在並設定為特定值。

1

2

3

4

5

6

7

8

9

10

11

12

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

    //業餘草:www.xttblog.com

}

參考資料