JWT初識記錄


因為前一段時間做了一個系統持續操作期間自動刷新token有效性的需求,然后就想着找一個空閑時間總結一下JWT,所以今天就簡單的記錄一下自己了解的內容。


JWT是什么

  1. JWT全稱是JSON Web Token,是一個開放標准,它定義了一種緊湊的、自包含的結構,可用於在服務之間信息傳遞和授權認證。
  • 信息傳遞:通過簽名,可以確保傳遞的信息不被篡改且不是偽造的。
  • 授權認證:通過JWT生成的token信息進行驗簽,確保是自己服務簽發的token信息。
  1. JWT的格式:

JWT由三部分組成,各部分之間使用[.]進行連接。各部分分別是:Header(頭信息)、Payload(載荷)和Signature(簽名)。

其格式如下:

header.payload.signature
  1. 使用場景

前端頁面點擊登錄,后端驗證用戶名密碼通過后,使用JWT生成token信息返回給前端,前端使用登錄token請求各個接口。


JWT使用示例

首先引入JWT jar包如下:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.6.0</version>
</dependency>

Java示例代碼如下:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.*;

public class JWTDemo {

    public static void main(String[] args) {
        String issue = "ISSUE_CESHI";
        // 簽名算法
        SignatureAlgorithm algorithm = SignatureAlgorithm.HS256;
        // 簽名秘鑰
        String secret = "CESHI_SECRET";
        int timeout = 60 * 60 * 6;

        long currentTime = System.currentTimeMillis();
        Map<String,Object> map = new HashMap<>();
        map.put("userId","10");
        map.put("userName","張三");

        String token = Jwts.builder()
                .signWith(algorithm, secret)
                .setClaims(map)
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date(currentTime))
                .setIssuer(issue)
                .setExpiration(new Date(currentTime + timeout * 1000))
                .compact();
        System.out.println(token);

        Jws<Claims> parseResult3 = Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
    }
}

上面演示代碼生成的token信息如下:

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJJU1NVRV9DRVNISSIsInVzZXJOYW1lIjoi5byg5LiJIiwiZXhwIjoxNjEwMzgzMzY0LCJ1c2VySWQiOiIxMCIsImlhdCI6MTYxMDM2MTc2NCwianRpIjoiY2QwNDM1ODctNGZmNS00OGY4LTk2YjUtNTA1ZTc4MzFkMGNjIn0.b_Fr8hpTC5nlwR4NikbEg1WpDMya2Gr5fCfNTV0iCOQ

然后將生成的token進行解析得到如下內容:

可以看到載荷里面有我們設置的userId和userName信息。

同時,JWT規定了7個官方的字段,如下:

  • iss (issuer):簽發人
  • exp (expiration time):過期時間
  • sub (subject):主題
  • aud (audience):受眾
  • nbf (Not Before):生效時間
  • iat (Issued At):簽發時間
  • jti (JWT ID):編號

需要特別注意的是,JWT的header和body部分都是用Base64進行編碼的,本身不具有加密屬性,所以在body中不能存儲敏感信息。


系統持續操作自動刷新token

JWT的一大優點就是token信息存儲在客戶端,服務端不用存儲對應的授權信息。因此,它的一大缺點就是一旦token頒發了就沒辦法進行撤銷,只有等待token自動失效。

如果想要實現token失效前撤銷,那么只能借助其他手段,比如使用redis緩存,token驗證除了JWT本身的驗簽外,還需要判斷redis緩存信息,但是這樣做有違JWT的設計本意。

說說在項目中遇到的需求:就是在用戶持續間隔時間內操作系統,那么系統內部應該自動刷新token信息,而不是在固定時間點強行要求重新登錄。比如token頒發的有效期是5個小時,然后用戶一直操作到4小時59分59秒,然后在5小時0分1秒的時候提交一個表格,這時如果因為token失效直接跳轉到登錄頁面,這樣的用戶體驗感是極為糟糕的。

所以為了解決上面的場景,在寫這個需求的時候,特地調研了一下各種方案,最后綜合了一下,決定采用redis實現。方案如下:

頒發一個足夠時長的token(比如15天),然后存儲在redis中,redis中設置短的有效期,比如6小時。從而實現在6小時內有效操作免登錄。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM