JWT 密鑰的解析和加密 工具類
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import java.util.UUID;
/**
* JWT 密鑰的解析和加密 工具類
*/
public class JwtUtils {
private static final String JWT_PAYLOAD_USER_KEY = "user";
/**
* 私鑰加密token
*
* @param userInfo 載荷中的數據
* @param privateKey 私鑰
* @param expire 過期時間,單位分鐘
* @return JWT
*/
public static String generateTokenExpireInMinutes(Object userInfo, PrivateKey privateKey, int expire) {
return Jwts.builder()
.claim(JWT_PAYLOAD_USER_KEY, JsonUtils.toString(userInfo))
.setId(createJTI())
.setExpiration(DateTime.now().plusMinutes(expire).toDate())
.signWith(privateKey, SignatureAlgorithm.RS256)
.compact();
}
/**
* 私鑰加密token
*
* @param userInfo 載荷中的數據
* @param privateKey 私鑰
* @param expire 過期時間,單位秒
* @return JWT
*/
public static String generateTokenExpireInSeconds(Object userInfo, PrivateKey privateKey, int expire) {
return Jwts.builder()
.claim(JWT_PAYLOAD_USER_KEY, JsonUtils.toString(userInfo))
.setId(createJTI())
.setExpiration(DateTime.now().plusSeconds(expire).toDate())
.signWith(privateKey, SignatureAlgorithm.RS256)
.compact();
}
/**
* 公鑰解析token
*
* @param token 用戶請求中的token
* @param publicKey 公鑰
* @return Jws<Claims>
*/
private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
}
private static String createJTI() {
return new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes()));
}
/**
* 獲取token中的用戶信息
*
* @param token 用戶請求中的令牌
* @param publicKey 公鑰
* @return 用戶信息
*/
public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey, Class<T> userType) {
Jws<Claims> claimsJws = parserToken(token, publicKey);
Claims body = claimsJws.getBody();
Payload<T> claims = new Payload<>();
claims.setId(body.getId());
claims.setUserInfo(JsonUtils.toBean(body.get(JWT_PAYLOAD_USER_KEY).toString(), userType));
claims.setExpiration(body.getExpiration());
return claims;
}
/**
* 獲取token中的載荷信息
*
* @param token 用戶請求中的令牌
* @param publicKey 公鑰
* @return 用戶信息
*/
public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey) {
Jws<Claims> claimsJws = parserToken(token, publicKey);
Claims body = claimsJws.getBody();
Payload<T> claims = new Payload<>();
claims.setId(body.getId());
claims.setExpiration(body.getExpiration());
return claims;
}
}
RSA工具類 密鑰的創建、讀取功能(公鑰和私鑰)
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* RSA工具類 負責對RSA密鑰的創建、讀取功能(公鑰和私鑰)
*/
public class RsaUtils {
private static final int DEFAULT_KEY_SIZE = 2048; // 生成的大小
/**
* 從文件中讀取公鑰
*
* @param filename 公鑰保存路徑,相對於classpath
* @return 公鑰對象
* @throws Exception
*/
public static PublicKey getPublicKey(String filename) throws Exception {
byte[] bytes = readFile(filename);
return getPublicKey(bytes);
}
/**
* 從文件中讀取密鑰
*
* @param filename 私鑰保存路徑,相對於classpath
* @return 私鑰對象
* @throws Exception
*/
public static PrivateKey getPrivateKey(String filename) throws Exception {
byte[] bytes = readFile(filename);
return getPrivateKey(bytes);
}
/**
* 獲取公鑰
*
* @param bytes 公鑰的字節形式
* @return
* @throws Exception
*/
private static PublicKey getPublicKey(byte[] bytes) throws Exception {
bytes = Base64.getDecoder().decode(bytes);
X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePublic(spec);
}
/**
* 獲取密鑰
*
* @param bytes 私鑰的字節形式
* @return
* @throws Exception
*/
private static PrivateKey getPrivateKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
bytes = Base64.getDecoder().decode(bytes);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePrivate(spec);
}
/**
* 根據密文,生存rsa公鑰和私鑰,並寫入指定文件
*
* @param publicKeyFilename 公鑰文件路徑
* @param privateKeyFilename 私鑰文件路徑
* @param secret 生成密鑰的密文
*/
public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret, int keySize) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(secret.getBytes());
keyPairGenerator.initialize(Math.max(keySize, DEFAULT_KEY_SIZE), secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
// 獲取公鑰並寫出
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
publicKeyBytes = Base64.getEncoder().encode(publicKeyBytes);
writeFile(publicKeyFilename, publicKeyBytes);
// 獲取私鑰並寫出
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
privateKeyBytes = Base64.getEncoder().encode(privateKeyBytes);
writeFile(privateKeyFilename, privateKeyBytes);
}
private static byte[] readFile(String fileName) throws Exception {
return Files.readAllBytes(new File(fileName).toPath());
}
private static void writeFile(String destPath, byte[] bytes) throws IOException {
File dest = new File(destPath);
if (!dest.exists()) {
dest.createNewFile();
}
Files.write(dest.toPath(), bytes);
}
}
JWT荷載 保存的數據對象
import lombok.Data;
import java.util.Date;
/**
* JWT荷載 保存的數據對象
* @param <T>
*/
@Data
public class Payload<T> {
private String id; // jwt的id(token)
private T userInfo; // 用戶信息:用戶數據,不確定,可以是任意類型
private Date expiration; // 過期時間
}