什么是 JWT?
JSON Web Token,通过数字签名的方式,以 ISON 对象为载体,在不同的服务终端之间安全的传输信息。
JWT有什么用?
JWT 最常见的场景就是授权认证,一旦用户登录,后续每个请求都将包含JWT,系统在每次处理用户请求的之前,都要先进行 JWT 安全校验,通过之后再进行处理。
JWT 的组成
JWT 由 3 部分组成,用.拼接
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
这三部分分别是:
- Header
{
"typ": "JWT",
"alg": "HS256"
}
- Payload
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
- Signature
var encodedstring = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret')
代码演示
依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
测试
package top.cluski.jjwtdemo;
import cn.hutool.jwt.JWTUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.Base64Codec;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
@SpringBootTest
public class JJwtDemoTests {
/**
* 创建token
*/
@Test
public void testCreateToken() {
JwtBuilder jwtBuilder = Jwts.builder()
.setHeaderParam("typ", "JWT")
// 声明的标识{"jti":"8888"}
.setId("8888")
// 主题,用户{"sub":"Rose"}
.setSubject("Rose")
// 创建日期{"ita":"xxx"}
.setIssuedAt(new Date())
// 设定盐
.signWith(SignatureAlgorithm.HS256, "wangyf");
// 获取jwt的token
String token = jwtBuilder.compact();
System.out.println(token);
System.out.println("============================");
String[] split = token.split("\\.");
System.out.println(Base64Codec.BASE64.decodeToString(split[0]));
System.out.println(Base64Codec.BASE64.decodeToString(split[1]));
// 签名是无法解密的
System.out.println(Base64Codec.BASE64.decodeToString(split[2]));
}
/**
* 解析token
*/
@Test
public void testParseToken() {
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODg4Iiwic3ViIjoiUm9zZSIsImlhdCI6MTY0ODgyMDExMn0.nWbSY58EE7lq2YWBPjNq8JkkAg9rzAuq0r-f-7XpH18";
// 解析token,获取负载中声明的对象
Claims claims = Jwts.parser()
.setSigningKey("wangyf")
.parseClaimsJws(token)
.getBody();
System.out.println("id: " + claims.getId());
System.out.println("subject: " + claims.getSubject());
System.out.println("issueAt: " + claims.getIssuedAt());
}
/**
* 创建token (失效时间)
*/
@Test
public void testCreateTokenExp() {
long now = System.currentTimeMillis();
long exp = now + 60 * 1000;
JwtBuilder jwtBuilder = Jwts.builder()
// 声明的标识{"jti":"8888"}
.setId("8888")
// 主题,用户{"sub":"Rose"}
.setSubject("Rose")
// 创建日期{"ita":"xxx"}
.setIssuedAt(new Date())
// 设定盐
.signWith(SignatureAlgorithm.HS256, "wangyf")
// 设置过期时间
.setExpiration(new Date(exp));
// 获取jwt的token
String token = jwtBuilder.compact();
System.out.println(token);
System.out.println("============================");
String[] split = token.split("\\.");
System.out.println(Base64Codec.BASE64.decodeToString(split[0]));
System.out.println(Base64Codec.BASE64.decodeToString(split[1]));
// 签名是无法解密的
System.out.println(Base64Codec.BASE64.decodeToString(split[2]));
}
/**
* 解析token (失效时间)
*/
@Test
public void testParseTokenExp() {
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODg4Iiwic3ViIjoiUm9zZSIsImlhdCI6MTY0ODgyMDYxNywiZXhwIjoxNjQ4ODIwNjc3fQ.88MP33KYfELb2dIjyNPKRBMhatNKAqSC_sIVZrY8_CY";
// 解析token,获取负载中声明的对象
Claims claims = Jwts.parser()
.setSigningKey("wangyf")
.parseClaimsJws(token)
.getBody();
System.out.println("id: " + claims.getId());
System.out.println("subject: " + claims.getSubject());
System.out.println("issueAt: " + claims.getIssuedAt());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("签发时间" + simpleDateFormat.format(claims.getIssuedAt()));
System.out.println("过期时间" + simpleDateFormat.format(claims.getExpiration()));
System.out.println("当前时间" + simpleDateFormat.format(new Date()));
}
/**
* 创建token (自定义声明)
*/
@Test
public void testCreateTokenByClaims() {
long now = System.currentTimeMillis();
long exp = now + 60 * 1000;
JwtBuilder jwtBuilder = Jwts.builder()
// 声明的标识{"jti":"8888"}
.setId("8888")
// 主题,用户{"sub":"Rose"}
.setSubject("Rose")
// 创建日期{"ita":"xxx"}
.setIssuedAt(new Date())
// 设定盐
.signWith(SignatureAlgorithm.HS256, "wangyf")
// 设置过期时间
.setExpiration(new Date(exp))
// 自定义声明
.claim("roles", "admin")
.claim("log", "xxx.jpg");
// 获取jwt的token
String token = jwtBuilder.compact();
System.out.println(token);
System.out.println("============================");
String[] split = token.split("\\.");
System.out.println(Base64Codec.BASE64.decodeToString(split[0]));
System.out.println(Base64Codec.BASE64.decodeToString(split[1]));
// 签名是无法解密的
System.out.println(Base64Codec.BASE64.decodeToString(split[2]));
}
/**
* 解析token (自定义声明)
*/
@Test
public void testParseTokenByClaims() {
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODg4Iiwic3ViIjoiUm9zZSIsImlhdCI6MTY0ODgyMTA5NSwiZXhwIjoxNjQ4ODIxMTU1LCJyb2xlcyI6ImFkbWluIiwibG9nIjoieHh4LmpwZyJ9.rasA_qD27R_M1NvVs2qdU0QZKOG6-dttYDoQFDES6fc";
// 解析token,获取负载中声明的对象
Claims claims = Jwts.parser()
.setSigningKey("wangyf")
.parseClaimsJws(token)
.getBody();
System.out.println("id: " + claims.getId());
System.out.println("subject: " + claims.getSubject());
System.out.println("issueAt: " + claims.getIssuedAt());
System.out.println("roles: " + claims.get("roles"));
System.out.println("log: " + claims.get("log"));
}
}
评论区