JWT Token 介紹
1. 什么是 JWT Token?
JSON Web Token(JWT)是一種開放標準(RFC 7519),它定義了一種緊湊且自包含的方式,用于在各方之間作為JSON對象安全地傳輸信息。每個Token都是經過簽名的,因此你可以驗證發送者的身份并確保數據未被篡改。
2. JWT Token 的結構
一個JWT通常包含三部分:Header(頭部)、Payload(負載)和Signature(簽名)。
-
Header:通常包含兩部分:令牌的類型(即JWT)和所使用的簽名算法,如HMAC SHA256或RSA。
-
Payload:包含聲明(claims)。聲明有三種類型:注冊的聲明、公共的聲明和私有的聲明。
- 注冊的聲明:一組預定義的聲明,它們不是強制性的,但推薦使用,如iss(issuer,簽發人)、exp(expiration time,過期時間)、sub(subject,主題)等。
- 公共的聲明:可以添加任何信息,但要避免添加敏感信息,因為它們可以被解碼(盡管不能被篡改)。
- 私有的聲明:用于在信息的發送方和接收方之間共享信息,不應該包含敏感信息。
-
Signature:用于驗證消息在傳輸過程中沒有被更改,并且,對于使用私鑰簽名的Token,還可以驗證發送者的身份。
3. JWT Token 的工作流程
- 用戶使用用戶名和密碼登錄應用。
- 應用驗證用戶的憑據。
- 一旦驗證通過,應用會創建一個包含用戶信息和其他必要聲明的JWT,并使用一個秘鑰進行簽名。
- 應用將這個JWT返回給用戶。
- 用戶在隨后的每個請求中將JWT發送回服務器,通常是在HTTP請求的Authorization頭部中。
- 服務器通過驗證JWT的簽名來確認它是由服務器簽發的,并且沒有被篡改。
- 如果驗證通過,服務器處理請求。
4. 為什么使用 JWT Token?
- 無狀態和可擴展性:由于JWT包含所有必要的信息,服務器不需要保存用戶狀態,這使得JWT非常適合分布式系統和可擴展的Web應用。
- 安全:JWT可以通過使用強簽名算法來保證數據的完整性和驗證發送者的身份。
- 自包含:JWT包含了所有用戶驗證所需的信息,減少了需要查詢數據庫的次數。
5. 常用的 Java 解析工具類
在Java中,有多個庫可以用來創建和解析JWT,以下是一些常用的庫:
-
jjwt:由Netflix開發的一個輕量級庫,用于創建和解析JWT。
Maven依賴:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> -
auth0/java-jwt:Auth0提供的JWT庫,支持JWT的創建和解析。
Maven依賴:
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.18.1</version> </dependency> -
java-jwt:一個簡單易用的JWT庫,用于創建和解析JWT。
Maven依賴:
<dependency> <groupId>com.github.kevinsawicki</groupId> <artifactId>http-request</artifactId> <version>6.0</version> </dependency>
6. 示例代碼
以下是使用jjwt庫解析JWT的簡單示例:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtExample {
public static void main(String[] args) {
// 示例JWT字符串
String jwt = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UiLCJleHAiOjE2MTYyMzkwMjJ9.HSMxgZzouqL1tT4";
// 解析JWT
Jws<Claims> jws = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(jwt);
// 獲取Claims
Claims claims = jws.getBody();
System.out.println("Subject: " + claims.getSubject());
System.out.println("Expiration: " + claims.getExpiration());
}
}
請注意,實際使用中,你需要根據你的應用需求選擇合適的庫,并妥善保管用于簽名的秘鑰。