Java如何生成Jwt之使用Hutool实现Jwt
前置条件
项目中需要引入依赖:
xml
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.43</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>6.1.0-M1</version>
<scope>test</scope>
</dependency>
</dependencies>
1、RS256-使用Hutool生成JWT的简单示例
- 这里使用的加密模式为:RS256
payload是一些自定义的参数,一般不建议太多的自定义参数,且不可存放敏感数据- 这个示例仅作原理讲解使用,公钥和私钥是实时生成的没有存储下来
代码如下
java
@Test
public void testJwtRsa() throws Exception{
// 1. 生成RSA密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // RSA密钥长度
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
// 2. 创建签名器
JWTSigner signer = JWTSignerUtil.rs256(privateKey);
// 3. 设置JWT的payload(载荷)自定义参数
Map<String, Object> payload = new HashMap<>();
payload.put("name", "John Doe");
payload.put("admin", true);
// 4. 设置JWT的header(头部)
Map<String, Object> headers = new HashMap<>();
headers.put("typ", "JWT");
headers.put("alg", "RS256");
// 5. 创建JWT
String token = JWT.create()
.addHeaders(headers)
.addPayloads(payload)
// 订阅者ID
.setSubject("UID2026010100089")
//.addPayloads(payload)
// 设置过期时间(30分钟后)
.setExpiresAt(DateUtil.offsetMinute(new Date(), 30))
// 设置签发时间
.setIssuedAt(new Date())
// 生效时间
.setNotBefore(new Date())
// 设置签发者
.setIssuer("your-app-name")
.setJWTId(UUID.randomUUID().toString().replaceAll("-", ""))
// 设置受众
.setAudience("client-app")
// 使用RS256算法签名
.setSigner(signer)
.sign();
System.out.println("生成的JWT (RS256):");
System.out.println(token);
System.out.println();
// 6. 验证和解析JWT
JWT jwt = JWT.of(token);
// 创建验证签名器
JWTSigner verifier = JWTSignerUtil.rs256(publicKey);
// 验证签名
boolean verifyResult = jwt.setSigner(verifier).verify();
System.out.println("签名验证结果: " + verifyResult);
// 验证过期时间
boolean validateResult = jwt.validate(0);
System.out.println("JWT验证结果: " + validateResult);
// 7. 获取payload数据
System.out.println("\nPayload数据:");
System.out.println("Subject: " + jwt.getPayload("sub"));
System.out.println("Name: " + jwt.getPayload("name"));
System.out.println("Admin: " + jwt.getPayload("admin"));
System.out.println("签发者: " + jwt.getPayload("iss"));
System.out.println("过期时间: " + jwt.getPayload("exp"));
}
2、使用固定的公钥私钥
- JWT签名使用公钥
- JWT验签使用私钥
- 因此一般私钥一定要在服务端保存好,一般需要通过
加密存储,或者使用限制权限读取的方式进行保存
2.1、生成RSA的密钥对
这里我提供了基于hutool的两种方式,如下代码示例:
java
@Test
public void testGenerateRsaKey() throws Exception {
// 1、生成默认的RSA密钥对
RSA rsa = new RSA();
String privateKeyBase64 = rsa.getPrivateKeyBase64();
String publicKeyBase64 = rsa.getPublicKeyBase64();
System.out.println("privateKeyBase64:" + privateKeyBase64);
System.out.println("publicKeyBase64:" + publicKeyBase64);
// 2、指定生成的密钥长度
KeyPair rsa1 = SecureUtil.generateKeyPair("RSA", 2048);
System.out.println("rsa1.privateKey:" + Base64.encode(rsa1.getPrivate().getEncoded()));
System.out.println("rsa1.publicKey:" + Base64.encode(rsa1.getPublic().getEncoded()));
}
2.2、使用固定的公私玥生成JWT及验证JWT示例
我这里仅作示例,公钥和私钥明文展示,一般在生产环境,密钥必须加密
java
@Test
public void testGenerateJwtFromRsa() throws Exception {
String publicKeyBase64 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCI0CZ/FiZcpaddf+zRmRc0g6gWBINrucBRuAjlyfNOAXe8H18Xwnj/4c4duMlg4bBlOyYlQ0wo8/k7URDcLE6kRORedRDkJW1OeWsdaqzTAJ+9rkZUN5w5CZsgLvaRYY2Tl1Whai6WFgyJPguT5ojl7DSc44lBnG9cCeMK2O9QEQIDAQAB";
String privateKeyBase64 = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIjQJn8WJlylp11/7NGZFzSDqBYEg2u5wFG4COXJ804Bd7wfXxfCeP/hzh24yWDhsGU7JiVDTCjz+TtRENwsTqRE5F51EOQlbU55ax1qrNMAn72uRlQ3nDkJmyAu9pFhjZOXVaFqLpYWDIk+C5PmiOXsNJzjiUGcb1wJ4wrY71ARAgMBAAECgYAqIZ+ZR2Ls6P6PZpOxQCnLPDgI/77Q79Tv1XK4AObyQLV0s1x/Xp4QfqMQuBUbxqShqANpOj475lX8FEzS4Loem5JeVGNpevNd3HYCVf7ylaWi7wzMm5y/y/O/dJb4o2Fk+6WODbZ9/fKIPDfOgKTyPYD8kZgufRLuvGBqATUreQJBAKCWYUQ5Dhs9xWLia+8FMjF5KnQVLbU48vlaIvb7H19cmpH7iT9B5fZwB+0xaWG4YMpSY39VcY4NJVrXBARw9ssCQQDaGadbfe31Uk5pUKsKCRbLI7n1EIEy45kp9WWIRScJzTd3bh1NMPxGrFVKdWqE+Ubr6HBO6H2drQeVAO9+yB0TAkBc31uVZyHfY1QaojQl4e1ra1XAGNd8bVkoGJcMG6PDNP033C895FCou5X5+Y+msklX+VoNtE6eBsBJzvxFzUcNAkAF6eYoy+xU14t6vY41snNkxK45H95w88zmX1oGbOGXGXJkkZ7HxglBHVEeuLpPqraqlN3etd0aFmP7PVBBHsnzAkBcZJv/Jue8PGHgfeNHS1hj4R7DRX0b3MLxyvFjloF3rjd56IuLJN9BXfiY8L+upcTsIP+B9hkstt5ge7/McJsy";
// 加载生成密钥对
PrivateKey privateKey = loadPrivateKey(privateKeyBase64);
PublicKey publicKey = loadPublicKey(publicKeyBase64);
// 2. 创建签名器
JWTSigner signer = JWTSignerUtil.rs256(privateKey);
// 3. 设置JWT的payload(载荷)自定义参数
Map<String, Object> payload = new HashMap<>();
payload.put("name", "John Doe");
payload.put("admin", true);
// 4. 设置JWT的header(头部)
Map<String, Object> headers = new HashMap<>();
headers.put("typ", "JWT");
headers.put("alg", "RS256");
// 5. 创建JWT
String token = JWT.create()
.addHeaders(headers)
.addPayloads(payload)
// 订阅者ID
.setSubject("UID2026010100089")
//.addPayloads(payload)
// 设置过期时间(30分钟后)
.setExpiresAt(DateUtil.offsetMinute(new Date(), 30))
// 设置签发时间
.setIssuedAt(new Date())
// 生效时间
.setNotBefore(new Date())
// 设置签发者
.setIssuer("your-app-name")
.setJWTId(UUID.randomUUID().toString().replaceAll("-", ""))
// 设置受众
.setAudience("client-app")
// 使用RS256算法签名
.setSigner(signer)
.sign();
System.out.println("生成的JWT (RS256):");
System.out.println(token);
System.out.println();
// 6. 验证和解析JWT
JWT jwt = JWT.of(token);
// 创建验证签名器
JWTSigner verifier = JWTSignerUtil.rs256(publicKey);
// 验证签名
boolean verifyResult = jwt.setSigner(verifier).verify();
System.out.println("签名验证结果: " + verifyResult);
// 验证过期时间
boolean validateResult = jwt.validate(0);
System.out.println("JWT验证结果: " + validateResult);
// 7. 获取payload数据
System.out.println("\nPayload数据:");
System.out.println("Subject: " + jwt.getPayload("sub"));
System.out.println("Name: " + jwt.getPayload("name"));
System.out.println("Admin: " + jwt.getPayload("admin"));
System.out.println("签发者: " + jwt.getPayload("iss"));
System.out.println("过期时间: " + jwt.getPayload("exp"));
}
/**
* 加载RSA私钥
* @param base64PrivateKey
* @return
*/
public static PrivateKey loadPrivateKey(String base64PrivateKey) {
byte[] keyBytes = Base64.decode(base64PrivateKey);
return KeyUtil.generateRSAPrivateKey(keyBytes);
}
/**
* 加载RSA公钥
* @param base64PublicKey
* @return
*/
public static PublicKey loadPublicKey(String base64PublicKey) {
byte[] keyBytes = Base64.decode(base64PublicKey);
return KeyUtil.generateRSAPublicKey(keyBytes);
}