package com.zway.common.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Date;
/**
* JWT校驗工具類
* <ol>
* <li>iss: jwt簽發(fā)者</li>
* <li>sub: jwt所面向的用戶</li>
* <li>aud: 接收jwt的一方</li>
* <li>exp: jwt的過期時間,這個過期時間必須要大于簽發(fā)時間</li>
* <li>nbf: 定義在什么時間之前,該jwt都是不可用的</li>
* <li>iat: jwt的簽發(fā)時間</li>
* <li>jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊</li>
* </ol>
*/
public class JWTUtil {
/**
* JWT 加解密類型
*/
private static final SignatureAlgorithm JWT_ALG = SignatureAlgorithm.HS256;
/**
* JWT 生成密鑰使用的密碼
*/
private static final String JWT_RULE = "wjtree.xin";
/**
* JWT 添加至HTTP HEAD中的前綴
*/
private static final String JWT_SEPARATOR = "Bearer ";
private static final Integer duration = 60 * 60 * 1000;
/**
* 使用JWT默認方式,生成加解密密鑰
*
* @param alg 加解密類型
* @return
*/
public static SecretKey generateKey(SignatureAlgorithm alg) {
return MacProvider.generateKey(alg);
}
/**
* 使用指定密鑰生成規(guī)則,生成JWT加解密密鑰
*
* @param alg 加解密類型
* @param rule 密鑰生成規(guī)則
* @return
*/
public static SecretKey generateKey(SignatureAlgorithm alg, String rule) {
// 將密鑰生成鍵轉(zhuǎn)換為字節(jié)數(shù)組
byte[] bytes = Base64.decodeBase64(rule);
// 根據(jù)指定的加密方式,生成密鑰
return new SecretKeySpec(bytes, alg.getJcaName());
}
/**
* 構(gòu)建JWT
*
* @param username jwt 面向的用戶
* @param userId jwt 唯一身份標識
* @return JWT字符串
*/
public static String buildJWT(String username, String userId) {
// 獲取JWT字符串
Date date = new Date();
Date durationDate = new Date(date.getTime() + duration);
String compact = Jwts.builder()
.signWith(JWT_ALG, generateKey(JWT_ALG, JWT_RULE))
.setSubject(username)
.setId(userId)
.setIssuedAt(new Date())
.setExpiration(durationDate)
.compact();
// 在JWT字符串前添加"Bearer "字符串,用于加入"Authorization"請求頭
//return JWT_SEPARATOR + compact;
return compact;
}
/**
* 構(gòu)建JWT
*
* @param username jwt 面向的用戶
* @param userId jwt 唯一身份標識
* @return JWT字符串
*/
public static String buildJWT(String username, String userId,Long duration) {
// 獲取JWT字符串
Date date = new Date();
Date durationDate = new Date(date.getTime() + duration);
String compact = Jwts.builder()
.signWith(JWT_ALG, generateKey(JWT_ALG, JWT_RULE))
.setSubject(username)
.setId(userId)
.setIssuedAt(new Date())
.setExpiration(durationDate)
.compact();
// 在JWT字符串前添加"Bearer "字符串,用于加入"Authorization"請求頭
//return JWT_SEPARATOR + compact;
return compact;
}
/**
* 解析JWT
*
* @param key jwt 加密密鑰
* @param claimsJws jwt 內(nèi)容文本
* @return {@link Jws}
* @throws Exception
*/
public static Jws<Claims> parseJWT(Key key, String claimsJws) {
// 移除 JWT 前的"Bearer "字符串
// claimsJws = StringUtils.substringAfter(claimsJws, JWT_SEPARATOR);
// 解析 JWT 字符串
return Jwts.parser().setSigningKey(key).parseClaimsJws(claimsJws);
}
/**
* 校驗JWT
*
* @param claimsJws jwt 內(nèi)容文本
* @return ture or false
*/
public static Boolean checkJWT(String claimsJws) {
boolean flag = false;
try {
SecretKey key = generateKey(JWT_ALG, JWT_RULE);
// 獲取 JWT 的 payload 部分
flag = (parseJWT(key, claimsJws).getBody() != null);
} catch (Exception e) {
}
return flag;
}
/**
* 校驗JWT
*
* @param key jwt 加密密鑰
* @param claimsJws jwt 內(nèi)容文本
* @param sub jwt 面向的用戶
* @return ture or false
*/
public static Boolean checkJWT(Key key, String claimsJws, String sub) {
boolean flag = false;
try {
// 獲取 JWT 的 payload 部分
Claims claims = parseJWT(key, claimsJws).getBody();
// 比對JWT中的 sub 字段
flag = claims.getSubject().equals(sub);
} catch (Exception e) {
}
return flag;
}
/**
* 校驗JWT
*
* @param claimsJws jwt 內(nèi)容文本
* @param sub jwt 面向的用戶
* @return ture or false
*/
public static Boolean checkJWT(String claimsJws, String sub) {
return checkJWT(generateKey(JWT_ALG, JWT_RULE), claimsJws, sub);
}
public static Claims getClaims(String claimsJws) {
Claims claims = parseJWT(generateKey(JWT_ALG, JWT_RULE), claimsJws).getBody();
return claims;
}
}
浙公網(wǎng)安備 33010602011771號