在2023年10月,JSON Web Token(JWT)仍然是廣泛使用的標準之一,用於在應用程序之間安全地傳輸數據。其中最流行的實現之一是`jsonwebtoken/jjwt`庫,它提供了一個易於使用的API來創建、驗證和解析JWT令牌。本文將介紹如何使用`jjwt`版本v0.12.3進行基本的操作。
安裝與導入
首先,確保你已經安裝了Java開發環境,並且Maven或Gradle已經配置好。然後你可以通過以下命令從Maven中央存儲庫中獲取`jjwt`:
mvn install:install-file -DgroupId=io.jsonwebtoken -DartifactId=jjwt -Dversion=0.12.3 -Dpackaging=jar -DgeneratePom=true -Dfile=<path_to_jjwt_0.12.3.jar>
或者,如果你使用的是Gradle,可以在build.gradle文件中添加以下依賴項:
dependencies {
implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.12.3'
}
一旦安裝完成,你就可以在你的Java項目中導入`jjwt`包:
import io.jsonwebtoken.*;
創建JWT
要創建一個JWT,你需要指定三個部分:Header、Payload和Signature。我們通常使用Base64編碼來表示這些部分。
Header
Header包含了token的類型(”JWT”)以及加密算法。例如:
Map<String, Object> header = new HashMap<>();
header.put("alg", "HS512"); // HMAC with SHA-512 hash algorithm
header.put("typ", "JWT"); // JWT type (mandatory)
String encodedHeader = Base64UrlEncoder.encodeAsString(new JSONObject(header).toString());
Payload
Payload包含了我們想要傳遞給接收方的 Claims(聲明)。這裏有一些常用的Claims:
Map<String, Object> claims = new HashMap<>();
claims.put("iss", "https://example.com"); // Issuer (claim issued by)
claims.put("exp", System.currentTimeMillis() / 1000L + 3600); // Expiration time (seconds since epoch)
encodedPayload = Base64UrlEncoder.encodeAsString(new JSONObject(claims).toString());
Signature
最後,我們將創建簽名部分。我們需要提供一個密鑰來計算HMACSHA-512哈希值,並將結果轉換爲Base64URL格式。
byte[] keyBytes = "secretkeyhere".getBytes(StandardCharsets.UTF_8);
SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA512");
String signature = Base64UrlEncoder.encodeAsString(jwsAlgorithm.sign(key, encodedHeader + "." + encodedPayload));
現在我們已經有了所有部分,我們可以組合它們形成一個完整的JWT字符串:
String token = encodedHeader + "." + encodedPayload + "." + signature;
驗證JWT
爲了驗證JWT,我們需要檢查它的有效性,比如檢查過期時間、算法、簽名的正確性和其他Claims的有效性。下面是如何驗證上述示例中的JWT:
// Verify the JWT and get back the original claims
try {
JWSVerifier verifier = jwsAlgorithm.createVerifier(key);
SignedJWT signedToken = SignedJWT.require(verifier).withCompactSerialization(token).build();
JWTVerificationResult result = signedToken.verify(verifier);
if (result.isValid()) {
System.out.println("The JWT is valid!");
// Access the claims
JWTClaimsSet claimsSet = signedToken.getJWTClaimsSet();
for (Map.Entry<?, ?> entry : claimsSet.getClaims().entrySet()) {
System.out.printf("Claim [%s] = %s\n", entry.getKey(), entry.getValue());
}
} else {
result.forEachFailure(failure -> System.out.println("Validation failed due to: " + failure));
}
} catch (Exception e) {
e.printStackTrace();
}
請注意,在實際應用中,你應該始終對用戶輸入的數據保持警惕,以防止惡意攻擊,如重放攻擊、跨站腳本攻擊等。此外,在使用任何密碼學原語時,都應該遵循相應的安全最佳實踐。