headerClaims是一个Map,包括两个属性typ和alg,typ值固定JWT,alg传过来的签名算法这里使用的
HmacSHA256简称HS256 。typ和alg组成Header头信息 。
Payload载荷结构分析关键源码如下:
public abstract class JWT { public JWT() { } public static DecodedJWT decode(String token) throws JWTDecodeException { return new JWTDecoder(token); } public static Verification require(Algorithm algorithm) { return JWTVerifier.init(algorithm); } public static Builder create() { return JWTCreator.init(); }}public static class Builder { private final Map<String, Object> payloadClaims = new HashMap(); private Map<String, Object> headerClaims = new HashMap(); Builder() { } public JWTCreator.Builder withHeader(Map<String, Object> headerClaims) { this.headerClaims = new HashMap(headerClaims); return this; } public JWTCreator.Builder withKeyId(String keyId) { this.headerClaims.put("kid", keyId); return this; } public JWTCreator.Builder withIssuer(String issuer) { this.addClaim("iss", issuer);//签发人 return this; } public JWTCreator.Builder withSubject(String subject) { this.addClaim("sub", subject);//主题 return this; } public JWTCreator.Builder withAudience(String... audience) { this.addClaim("aud", audience);//接受一方 return this; } public JWTCreator.Builder withExpiresAt(Date expiresAt) { this.addClaim("exp", expiresAt);//过期时间 return this; } public JWTCreator.Builder withNotBefore(Date notBefore) { this.addClaim("nbf", notBefore);//生效时间 return this; } public JWTCreator.Builder withIssuedAt(Date issuedAt) { this.addClaim("iat", issuedAt);//签发时间 return this; } public JWTCreator.Builder withJWTId(String jwtId) { this.addClaim("jti", jwtId);//编号 return this; } public JWTCreator.Builder withClaim(String name, Boolean value) throws IllegalArgumentException { this.assertNonNull(name); this.addClaim(name, value); return this; } public JWTCreator.Builder withClaim(String name, Integer value) throws IllegalArgumentException { this.assertNonNull(name); this.addClaim(name, value); return this; } //...其他方法省略...}Payload是一个json对象,存放需要传递的数据,JTW默认规定了几个属性,如果需要添加其他属性可以调用其重载方法witchClaim()添加 。
Signature签名部分源码如下:
private String sign() throws SignatureGenerationException { String header = Base64.encodeBase64URLSafeString( this.headerJson.getBytes(StandardCharsets.UTF_8)); String payload = Base64.encodeBase64URLSafeString( this.payloadJson.getBytes(StandardCharsets.UTF_8)); String content = String.format("%s.%s", header, payload); byte[] signatureBytes = this.algorithm.sign( content.getBytes(StandardCharsets.UTF_8)); String signature = Base64.encodeBase64URLSafeString(signatureBytes); return String.format("%s.%s", content, signature);}从这里可以看出,所谓token就是分别对header和payload的json字符串做Base64加密得到a和b,并将结果拼接一起,在进行签名得到c,最终把a、b、c三部分内容以点拼接起来形成token,返回客户端保存,客户端以后每次请求都在header中加入token,服务器采用拦截器方式获取header中的token做校验,识别用户 。
三、示例
3.1 数据准备
创建用户表

文章插图
3.2 搭建springboot工程

文章插图
设置工程Group、Artifact、Version、Name等信息

文章插图
Spring Boot的版本选择2.0.8,选择导入web的起步器

文章插图
创建工程成功之后,将各个包创建出来,工程目录结构如下:

文章插图
3.3 引入pom依赖

文章插图
文章插图
3.4%20编写application.yml配置文件

文章插图
3.5 编写User实体类

文章插图
Result类:用于统一返回消息的封装

文章插图
TokenUtil类,用于生成token

推荐阅读
- 10个 javascript精简代码集合
- Java BiFunction 接口实例
- Java对象的内存分配过程是如何保证线程安全的?
- JavaScript自定义事件
- 阿里P6面试题及答案
- JavaScript 常见10种函数
- 一线大厂JAVA面试精选:JVM+RabbitMQ+Mybatis+Redis+分布式+微服务
- 阿里内部的那个牛逼带闪电的Java诊断工具终于开源了
- Java多线程同步内部如何实现的
- OOP JavaScript面向对象编程