jwt是我们生成token的首选,我在第一次接触写token时,在网上找了很久,没有找到合适的,不是版本问题,就是残缺不全,很恶心。这篇文章我将jwt生成token的全过程写下,希望对初学者有帮助。
SpringBoot版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.10</version>
</parent>
jdk版本
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
jwt 所需依赖
<!--JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
</dependency>
Jwt工具类代码
复制后改成自己的类名就能正常使用。
我用的是私钥加密,公钥解密。
私钥和公钥可以用
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.Map;
/**
* JWT工具类
*
*/
public class JWTUtils {
/**
* 根据给定的密钥字符串获取私钥对象
* 该方法主要用于将Base64编码的私钥字符串解码并转换为PrivateKey对象
*
* @param key Base64编码的私钥字符串
* @return 转换后的私钥对象PrivateKey
* @throws RuntimeException 如果密钥字符串无效或算法不支持,将抛出运行时异常
*/
private static PrivateKey getPrivateKey(String key) {
byte[] decode = Base64.getDecoder().decode(key);
PrivateKey privateKey;
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpecPrivate = new PKCS8EncodedKeySpec(decode);
privateKey = keyFactory.generatePrivate(keySpecPrivate);
} catch (Exception e) {
throw new RuntimeException(e);
}
return privateKey;
}
/**
* 根据Base64编码的字符串获取RSA公钥
*
* @param key Base64编码的公钥字符串
* @return 转换后的RSA公钥
* <p>
* 注意:该方法使用Base64解码器将输入的字符串解码为字节数组,然后使用KeyFactory和X509EncodedKeySpec
* 将字节数组转换为PublicKey对象。如果转换过程中发生异常,将抛出RuntimeException。
*/
private static PublicKey getPublicKey(String key) {
byte[] decode = Base64.getDecoder().decode(key);
PublicKey publicKey;
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decode);
publicKey = keyFactory.generatePublic(keySpec);
} catch (Exception e) {
throw new RuntimeException(e);
}
return publicKey;
}
/**
* 创建JWT令牌
*
* @param subject 要转换为令牌的主题对象,通常是一个包含用户信息的对象
* @param expMillis 令牌过期时间戳,以毫秒为单位
* @param key 用于加密令牌的密钥,应保持安全以防止令牌被破解
* @return 返回生成的JWT令牌字符串
* <p>
* 此方法的作用是将一个Java对象(通常包含一些属性和值)转换为一个JWT令牌
* 它首先将主题对象转换为Map形式,这样可以更容易地将对象的属性和值包含在令牌中
* 然后使用JWT工具类的createToken方法,将Map和密钥作为参数,生成并返回JWT令牌
*/
public static String createToken(Object subject, Long expMillis, String key) {
String data = JSONUtils.toJsonStr(subject);
long nowMillis = System.currentTimeMillis();
// 有效期
Date expDate = new Date(expMillis);
// 唯一的ID
String uuid = String.valueOf(IdUtils.getSnowflake().nextId());
// 签发时间
Date now = new Date(nowMillis);
return Jwts.builder()
.setId(uuid)
.setSubject(data)
.setIssuer("xxx-xxx") //发行人
.setIssuedAt(now)
.setExpiration(expDate)
.signWith(getPrivateKey(key))
.compact();
}
/**
* 解析JWT令牌,获取其中的主体信息
*
* @param token 待解析的JWT令牌字符串
* @param key 用于验证JWT的密钥
* @return 解析出的JWT主体信息
*/
public static String parseToken(String token, String key) {
Claims claims = (Claims) Jwts.parserBuilder()
.setSigningKey(getPublicKey(key))
.build()
.parse(token)
.getBody();
return claims.getSubject();
}
/**
* 验证Token(Jwt)的有效性
*
* @param token 待验证的Token字符串
* @param key 用于解码Token的密钥
* @return 如果Token有效返回true,否则返回false
*/
public static Boolean verifyToken(String token, String key) {
// 尝试解析Token,如果解析失败则直接返回false
String parseToken = null;
try {
parseToken = parseToken(token, key);
} catch (Exception e) {
return false;
}
// 如果Token解析成功,将其转换为Map对象以便检查过期时间
if (parseToken != null) {
Map<String, Object> map = BeanUtils.beanToMap(parseToken);
String expireTime = map.get("expireTime").toString();
// 比较Token的过期时间和当前时间,判断Token是否过期
return Long.parseLong(expireTime) > System.currentTimeMillis();
}
return false;
}
自定义公钥私钥
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
public class RSAGenerator {
public static void generateKey() throws NoSuchAlgorithmException {
// 初始化密钥对生成器
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 设置密钥大小为2048位
// 生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 提取公钥和私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 将公钥和私钥转换为字符串
String publicKeyString = getPublicKeyAsString(publicKey);
String privateKeyString = getPrivateKeyAsString(privateKey);
System.out.println("Public Key: " + publicKeyString);
System.out.println("Private Key: " + privateKeyString);
}
public static String getPublicKeyAsString(RSAPublicKey publicKey) {
byte[] encoded = publicKey.getEncoded();
return Base64.getEncoder().encodeToString(encoded);
}
public static String getPrivateKeyAsString(RSAPrivateKey privateKey) {
byte[] encoded = privateKey.getEncoded();
return Base64.getEncoder().encodeToString(encoded);
}
}