JWT
流程图
JWT的结构
- 1.标头(Header)
- 2.有效载荷(Payload)
- 3.签名(Signature)
- 因此,JWT通常为Header.Payload.Signature。
Header
标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法(例如HMAC SHA256或RSA),如:
{
"alg": "HS256",
"typ": "JWT"
}
然后会使用 Base64 编码组成 JWT 结构的第一部分。
Payload
令牌的第二部分是有效负载,包含有关数据。如:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
同样的,它会使用 Base64 编码组成 JWT 结构的第二部分。 因为Base64是一种编码,是可逆的,所以不应该在负载里面加入任何敏感的数据。
Signature
-
Signature 需要使用编码后的 header 和 payload 以及我们提供的一个密钥,然后使用 header 中指定的签名算法(HS256)进行签名。如:
HMACSHA256(header + "." + payload,secret);
-
实际上是对头部以及负载内容进行签名,如果有人对头部以及负载的内容解码之后进行修改,再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断出新的头部和负载形成的签名和JWT附带上的签名是不一样的。如果要对新的头部和负载进行签名,在不知道服务器加密时用的密钥的话,新的头部和负载形成的签名和JWT附带上的签名也是不一样的。
JWT实际使用
@Test
void testJWT() throws Exception{
//1.生成JWT
Date expireTime=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2022-01-22 14:00:00");
//给payload中添加数据,一个数据是一个claim,过期时间其实就是一个claim(name是exp,value是过期时间.).
String token=JWT.create().withClaim("userId",1).withClaim("username","wjl").withExpiresAt(expireTime).sign(Algorithm.HMAC256("wjl123"));
System.out.println(token);
//2.验证JWT
//构建验证器
JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256("wjl123")).build();
//验证
DecodedJWT decodedJWT=jwtVerifier.verify(token);
//3.取出数据
System.out.println("userId: "+decodedJWT.getClaim("userId").asInt());
System.out.println("username: "+decodedJWT.getClaim("username").asString());
System.out.println("过期时间: "+decodedJWT.getExpiresAt());
//也可以这么获取过期时间
System.out.println("过期时间: "+decodedJWT.getClaim("exp").asDate());
}
个人总结
- JWT本质上和session作用一样,都是【认证+携带数据】(比只携带数据多了一个认证功能),但是比session更高效(和后端服务器无关)。
- 在同一数据的情况下,JWT只和密钥有关。