由於前一段時間作了一個系統持續操做期間自動刷新token有效性的需求,而後就想着找一個空閒時間總結一下JWT,因此今天就簡單的記錄一下本身瞭解的內容。前端
JWT由三部分組成,各部分之間使用[.]進行鏈接。各部分分別是:Header(頭信息)、Payload(載荷)和Signature(簽名)。java
其格式以下:web
header.payload.signature
前端頁面點擊登陸,後端驗證用戶名密碼經過後,使用JWT生成token信息返回給前端,前端使用登陸token請求各個接口。redis
首先引入JWT jar包以下:算法
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.6.0</version> </dependency>
Java示例代碼以下:json
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信息。dom
同時,JWT規定了7個官方的字段,以下:ui
- iss (issuer):簽發人
- exp (expiration time):過時時間
- sub (subject):主題
- aud (audience):受衆
- nbf (Not Before):生效時間
- iat (Issued At):簽發時間
- jti (JWT ID):編號
須要特別注意的是,JWT的header和body部分都是用Base64進行編碼的,自己不具備加密屬性,因此在body中不能存儲敏感信息。
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小時內有效操做免登陸。