205 lines
6.0 KiB
Java
205 lines
6.0 KiB
Java
package com.bao.dating.util;
|
||
|
||
import io.jsonwebtoken.Claims;
|
||
import io.jsonwebtoken.Jwts;
|
||
import io.jsonwebtoken.SignatureAlgorithm;
|
||
import io.jsonwebtoken.security.Keys;
|
||
|
||
import javax.crypto.SecretKey;
|
||
import java.nio.charset.StandardCharsets;
|
||
import java.util.Date;
|
||
import java.util.HashMap;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* JWT工具类
|
||
* 提供JWT Token的生成、解析和验证功能
|
||
* @author KilLze
|
||
*/
|
||
public class JwtUtil {
|
||
|
||
/**
|
||
* 默认密钥(建议从配置文件读取)
|
||
*/
|
||
private static final String DEFAULT_SECRET = "dating-application-secret-key-for-jwt-token-generation-2025";
|
||
|
||
/**
|
||
* 默认过期时间(毫秒)- 7天
|
||
*/
|
||
private static final long DEFAULT_EXPIRATION = 7 * 24 * 60 * 60 * 1000L;
|
||
|
||
/**
|
||
* 生成JWT Token
|
||
* @param subject 主题(通常是用户ID或用户名)
|
||
* @return JWT Token字符串
|
||
*/
|
||
public static String generateToken(String subject) {
|
||
return generateToken(subject, DEFAULT_EXPIRATION);
|
||
}
|
||
|
||
/**
|
||
* 生成JWT Token(自定义过期时间)
|
||
* @param subject 主题(通常是用户ID或用户名)
|
||
* @param expiration 过期时间(毫秒)
|
||
* @return JWT Token字符串
|
||
*/
|
||
public static String generateToken(String subject, long expiration) {
|
||
return generateToken(subject, expiration, null);
|
||
}
|
||
|
||
/**
|
||
* 生成JWT Token(带自定义claims)
|
||
* @param subject 主题(通常是用户ID或用户名)
|
||
* @param expiration 过期时间(毫秒)
|
||
* @param claims 自定义claims
|
||
* @return JWT Token字符串
|
||
*/
|
||
public static String generateToken(String subject, long expiration, Map<String, Object> claims) {
|
||
Date now = new Date();
|
||
Date expiryDate = new Date(now.getTime() + expiration);
|
||
|
||
SecretKey key = getSecretKey();
|
||
|
||
if (claims == null) {
|
||
claims = new HashMap<>();
|
||
}
|
||
|
||
return Jwts.builder()
|
||
.setClaims(claims)
|
||
.setSubject(subject)
|
||
.setIssuedAt(now)
|
||
.setExpiration(expiryDate)
|
||
.signWith(key, SignatureAlgorithm.HS256)
|
||
.compact();
|
||
}
|
||
|
||
/**
|
||
* 生成JWT Token(使用自定义密钥)
|
||
* @param subject 主题
|
||
* @param expiration 过期时间(毫秒)
|
||
* @param secret 自定义密钥
|
||
* @return JWT Token字符串
|
||
*/
|
||
public static String generateTokenWithSecret(String subject, long expiration, String secret) {
|
||
Date now = new Date();
|
||
Date expiryDate = new Date(now.getTime() + expiration);
|
||
|
||
SecretKey key = getSecretKey(secret);
|
||
|
||
return Jwts.builder()
|
||
.setSubject(subject)
|
||
.setIssuedAt(now)
|
||
.setExpiration(expiryDate)
|
||
.signWith(key, SignatureAlgorithm.HS256)
|
||
.compact();
|
||
}
|
||
|
||
/**
|
||
* 从Token中获取Claims
|
||
* @param token JWT Token
|
||
* @return Claims对象
|
||
*/
|
||
public static Claims getClaimsFromToken(String token) {
|
||
return getClaimsFromToken(token, DEFAULT_SECRET);
|
||
}
|
||
|
||
/**
|
||
* 从Token中获取Claims(使用自定义密钥)
|
||
* @param token JWT Token
|
||
* @param secret 密钥
|
||
* @return Claims对象
|
||
*/
|
||
public static Claims getClaimsFromToken(String token, String secret) {
|
||
try {
|
||
SecretKey key = getSecretKey(secret);
|
||
return Jwts.parserBuilder()
|
||
.setSigningKey(key)
|
||
.build()
|
||
.parseClaimsJws(token)
|
||
.getBody();
|
||
} catch (Exception e) {
|
||
throw new RuntimeException("解析JWT Token失败", e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 从Token中获取主题(通常是用户ID)
|
||
* @param token JWT Token
|
||
* @return 主题字符串
|
||
*/
|
||
public static String getSubjectFromToken(String token) {
|
||
Claims claims = getClaimsFromToken(token);
|
||
return claims.getSubject();
|
||
}
|
||
|
||
/**
|
||
* 验证Token是否有效
|
||
* @param token JWT Token
|
||
* @return 是否有效
|
||
*/
|
||
public static boolean validateToken(String token) {
|
||
return validateToken(token, DEFAULT_SECRET);
|
||
}
|
||
|
||
/**
|
||
* 验证Token是否有效(使用自定义密钥)
|
||
* @param token JWT Token
|
||
* @param secret 密钥
|
||
* @return 是否有效
|
||
*/
|
||
public static boolean validateToken(String token, String secret) {
|
||
try {
|
||
Claims claims = getClaimsFromToken(token, secret);
|
||
return !isTokenExpired(claims);
|
||
} catch (Exception e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查Token是否过期
|
||
* @param claims Claims对象
|
||
* @return 是否过期
|
||
*/
|
||
private static boolean isTokenExpired(Claims claims) {
|
||
Date expiration = claims.getExpiration();
|
||
return expiration.before(new Date());
|
||
}
|
||
|
||
/**
|
||
* 获取Token的过期时间
|
||
* @param token JWT Token
|
||
* @return 过期时间
|
||
*/
|
||
public static Date getExpirationDateFromToken(String token) {
|
||
Claims claims = getClaimsFromToken(token);
|
||
return claims.getExpiration();
|
||
}
|
||
|
||
/**
|
||
* 获取默认密钥的SecretKey对象
|
||
* @return SecretKey对象
|
||
*/
|
||
private static SecretKey getSecretKey() {
|
||
return getSecretKey(DEFAULT_SECRET);
|
||
}
|
||
|
||
/**
|
||
* 根据字符串密钥生成SecretKey对象
|
||
* @param secret 密钥字符串
|
||
* @return SecretKey对象
|
||
*/
|
||
private static SecretKey getSecretKey(String secret) {
|
||
// 确保密钥长度至少为256位(32字节)以支持HS256算法
|
||
byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
|
||
if (keyBytes.length < 32) {
|
||
// 如果密钥太短,进行填充
|
||
byte[] paddedKey = new byte[32];
|
||
System.arraycopy(keyBytes, 0, paddedKey, 0, Math.min(keyBytes.length, 32));
|
||
return Keys.hmacShaKeyFor(paddedKey);
|
||
}
|
||
return Keys.hmacShaKeyFor(keyBytes);
|
||
}
|
||
}
|
||
|