1.jwt令牌是什么
全称
JSON Web Token
,是目前最流行的跨域身份验证解决方案
2.jwt数据结构
token分为三部分,header.payload.signatrue
以 .
号分隔
- header 头文件
- payload 有效荷载
- signatrue 签名文件
- header信息
如:签名使用的算法HS256,typ属性表示令牌的类型
{
"alg": "HS256",
"typ": "JWT"
}
- payload有效荷载
jwt默认提供了以下7个属性设置,也可以自定义属性字段(类似Map中设置)
默认参数:
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
- 签名哈希
签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload)
var signature = HMACSHA256(encodedString, 'secret')
最终解果 : token = base64UrlEncode(header)
+ '.' + base64UrlEncode(payload)
+ '.' + signature
代码测试
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.Test;
import java.util.Base64;
import java.util.Date;
public class JwtTest {
/**
* signature底层原理
* <p>
* var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload)<p>
* var signature = HMACSHA256(encodedString, 'secret')<p>
* 最终解果 : token = base64UrlEncode(header) + '.' + base64UrlEncode(payload) + '.' + signature<p>
* demo: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIwMDciLCJzdWIiOiJzaHVzbSIsImV4cCI6MTU1NDYyMzc2MiwibmJmIjoxNTU0NzA2NTYyLCJpYXQiOjE1NTQ2MjAxNjIsImlzcyI6Imp1bml0In0.GHyxmrcXzxnAHN8ib2209I48wUpIU1Pyr_-sGDucoMM<p>
* <p>
* <p>
* payload 建议使用参数:<p>
* iat jwt的签发时间<p>
* exp jwt的过期时间,这个过期时间必须要大于签发时间<p>
* nbf 定义在什么时间之前,该jwt都是不可用的<p>
*/
@Test
public void testJwt() {
String secret = "loveqq";// 密钥
String token = Jwts.builder().claim("userId", "007")
.setSubject("shusm")
// exp 有效期设置 - 1h失效
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
// .setExpiration(new Date(System.currentTimeMillis())) // 立刻超时
// nbf 明天才生效
// .setNotBefore(new DateTime().plusDays(1).toDate())
.setIssuedAt(new Date())
.setIssuer("junit")
// 签名设置
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
System.out.println("加密后access_token为:" + token);
// token分为三部分,header.payload.signatrue , 前2个部分可以直接用 base64 反向解析得出结果
String[] split = token.split("\\.");
String header = new String(Base64.getDecoder().decode(split[0].getBytes()));
System.out.println("header:" + header);
String payload = new String(Base64.getDecoder().decode(split[1].getBytes()));
System.out.println("payLoad:" + payload);
// token检验
Claims body = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
System.out.println("------------JWT解析结果--------------");
body.forEach((k, v) -> {
System.out.println("K:" + k + "\t v:" + v);
});
}
}
运行结果:
加密后access_token为:eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIwMDciLCJzdWIiOiJzaHVzbSIsImV4cCI6MTU1NDYyNjQ4MCwiaWF0IjoxNTU0NjIyODgwLCJpc3MiOiJqdW5pdCJ9.Ggfjx0dqUIjLLXHMs-s2Y_yLKcJCeAcwbmyTyx3h6T8
header:{"alg":"HS256"}
payLoad:{"userId":"007","sub":"shusm","exp":1554626480,"iat":1554622880,"iss":"junit"}
------------JWT解析结果--------------
K:userId v:007
K:sub v:shusm
K:exp v:1554626480
K:iat v:1554622880
K:iss v:junit
网友评论