-
jjwt介绍
JJW是一个提供端到端的JWT创建和验证的java库,永远免费和开源, JJWT很容易使用和理解,它被设置成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性
官网:https://github.com/jwtk/jjwt -
使用
新建项目引入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
测试类
package com.srr;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
@SpringBootTest
class SpringSecurityDemo01demoApplicationTests {
@Test
void test1() {
JwtBuilder jwtBuilder = Jwts.builder()
.setId("3070") //设置id
.setSubject("测试jwt") //主题
.setIssuedAt(new Date())// 签发日期
.signWith(SignatureAlgorithm.HS256, "srrsrr");//设置算法和盐
String jwt = jwtBuilder.compact();
System.out.println("jwt = "+jwt);
}
}
运行结果
运行结果第一次
jwt = eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIzMDcwIiwic3ViIjoi5rWL6K-Vand0IiwiaWF0IjoxNjc5OTEwMTc2fQ.pIA4py2vaZcpgW5s_TjCT7AA-UGscYfwvDp8UP9ijhw
运行结果第一次
jwt = eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIzMDcwIiwic3ViIjoi5rWL6K-Vand0IiwiaWF0IjoxNjc5OTEwMjMxfQ.VyIg6ekewT0bOF4U4ksXHHCdTPQYKQnG515nqj-nlNE
发现每次运行的结果不一样,因为我们的载荷中包含了时间
-
解析jwt
刚才已经创建了token,在web应用中这个操作是由服务端进行然后发给客户端,客户端在下次向服务 端发送请求时需要 携带这个jwt字符串,也就是token,那服务端拉到这个token应该解析出token中的信息,如id,根据这些信息查询数据库返回相应的结果
package com.srr;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
@SpringBootTest
class SpringSecurityDemo01demoApplicationTests {
@Test
void test1() {
JwtBuilder jwtBuilder = Jwts.builder()
.setId("3070") //设置id
.setSubject("测试jwt") //主题
.setIssuedAt(new Date())// 签发日期
.signWith(SignatureAlgorithm.HS256, "srrsrr");//设置算法和密钥
String jwt = jwtBuilder.compact();
System.out.println("jwt = "+jwt);
//解析token
Claims claims = Jwts.parser().setSigningKey("srrsrr").parseClaimsJws(jwt).getBody();
System.out.println(claims);
}
}
结果
{jti=3070, sub=测试jwt, iat=1679910666}
注意1:尝试将token或签名秘钥篡改一下,会发现运行时就报错,所以解析token也就是验证token
注意2: 设置签名key必须和生成时一致
-
设置过期时间
很多的时候,我们并不希望签发的token是永久生效的,所以可以为token添加一个过期时间
创建token并设置过期时间
package com.srr;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
@SpringBootTest
class SpringSecurityDemo01demoApplicationTests {
@Test
void test1() {
JwtBuilder jwtBuilder = Jwts.builder()
.setId("3070") //设置id
.setSubject("测试jwt") //主题
.setIssuedAt(new Date())// 签发日期
.signWith(SignatureAlgorithm.HS256, "srrsrr");//设置算法和密钥
String jwt = jwtBuilder.compact();
System.out.println("jwt = "+jwt);
Claims claims = Jwts.parser().setSigningKey("srrsrr1").parseClaimsJws(jwt).getBody();
System.out.println(claims);
}
@Test
void test2() {
JwtBuilder jwtBuilder = Jwts.builder()
.setId("3070") //设置id
.setSubject("测试token过期")//主题
.setIssuedAt(new Date())// 签发日期
.setExpiration(new Date(System.currentTimeMillis() + 10000))// 过期时间(当前时间+10秒)
.signWith(SignatureAlgorithm.HS256, "srr123"); //算法和盐
String jwt = jwtBuilder.compact();
System.out.println(jwt);
try {
//睡15秒
Thread.sleep(15000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//解析token
Claims claims = Jwts.parser().setSigningKey("srr123").parseClaimsJws(jwt).getBody();
System.out.println(claims);
}
}
结果 报错
io.jsonwebtoken.ExpiredJwtException: JWT expired at 2023-03-27T18:10:13Z. Current time: 2023-03-27T18:10:18Z, a difference of 5489 milliseconds. Allowed clock skew: 0 milliseconds.
...
Process finished with exit code -1
-
自定义claims
上面我们只是存储了id和subject两个信息,如果想要存储更多,可以自定义claims
package com.srr;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
@SpringBootTest
class SpringSecurityDemo01demoApplicationTests {
@Test
void test1() {
JwtBuilder jwtBuilder = Jwts.builder()
.setId("3070") //设置id
.setSubject("测试jwt") //主题
.setIssuedAt(new Date())// 签发日期
.signWith(SignatureAlgorithm.HS256, "srrsrr");//设置算法和密钥
String jwt = jwtBuilder.compact();
System.out.println("jwt = "+jwt);
Claims claims = Jwts.parser().setSigningKey("srrsrr1").parseClaimsJws(jwt).getBody();
System.out.println(claims);
}
@Test
void test2() {
JwtBuilder jwtBuilder = Jwts.builder()
.setId("3070") //设置id
.setSubject("测试token过期")//主题
.setIssuedAt(new Date())// 签发日期
.setExpiration(new Date(System.currentTimeMillis() + 10000))// 过期时间(当前时间+10秒)
.signWith(SignatureAlgorithm.HS256, "srr123"); //算法和盐
String jwt = jwtBuilder.compact();
System.out.println(jwt);
try {
//睡15秒
Thread.sleep(15000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//解析token
Claims claims = Jwts.parser().setSigningKey("srr123").parseClaimsJws(jwt).getBody();
System.out.println(claims);
}
@Test
void test3() {
JwtBuilder jwtBuilder = Jwts.builder()
.setId("3070") //设置Id
.setSubject("测试自定义claims") //主题
.setIssuedAt(new Date()) //签发日期
.claim("userId", "001") //自定义 claim
.setExpiration(new Date(System.currentTimeMillis() + 900000)) //过期时间
.signWith(SignatureAlgorithm.HS256, "srrabc"); //算法 和密钥
String jwt = jwtBuilder.compact(); //生成token
System.out.println(jwt);
//解析token
Claims claims = Jwts.parser().setSigningKey("srrabc").parseClaimsJws(jwt).getBody();
System.out.println(claims);
}
}
运行结果
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIzMDcwIiwic3ViIjoi5rWL6K-V6Ieq5a6a5LmJY2xhaW1zIiwiaWF0IjoxNjc5OTEyMjA5LCJ1c2VySWQiOiIwMDEiLCJleHAiOjE2Nzk5MTMxMDl9.GTmVsrEZb8VO-RUyYyt5tCVptPdirsLOZFnk4dgRpPk
{jti=3070, sub=测试自定义claims, iat=1679912209, userId=001, exp=1679913109}
版权声明:本文为qq_39828220原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。