1. JWT介绍
JWT是JSON Web Token的简称,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准,常用于登录认证,客户端请求时通过头部携带服务端生成的token令牌来验证身份。
2. JWT数据结构与原理
JWT令牌由头部(Header)、负载(Payload)、签名(Signature)三部分组成,每部分通过.符号连接,形式为
Header.Payload.Signature
2.1. 头部
JWT的头部是一个JSON对象,描述JWT的元数据类型,通常有两个字段:alg和typ, alg表示JWT的签名算法,默认是HS256算法,typ属性表示令牌的token类型,为JWT令牌时typ的值为JWT,
头部的常见形式如下:
{
“alg”:“HS256”,
“alg”:“JWT”
}
2.2. 负载
负载也是一个JSON对象,用来存放实际传输的数据,规定7个官方的字段如下:
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
除了7个官方字段外,我们还可以自定义要传输的字段,比如:
{
“account”: “12334556”,
“name”:“xiaoming”
}
由于JWT默认对传输数据不加密,所以不要通过JWT传输敏感信息。
2.3 签名
JWT采用签名的方式来验证传输的数据是否被篡改。通过指定一个签名密钥,对前两部分头部和负载通过Base64URL算法编码后的内容进行加密,生成签名部分的数据,头部、负载、签名三部分通过.符号进行连接,形成一个JWT的token令牌返回给客户端。如果数据被篡改,通过原来签名组成新的token令牌,服务器端通过被篡改数据生成的签名与原来的不一样,携带纂改数据的请求无发通过验证;如果替换掉原来的签名,由于不知道服务器的加密秘钥,也无法通过认证。以HS256加密算法为例,生成签名的公式如下:
HS256(BaseURLEncode(Header) + “.” + BaseURLEncode(Payload), secret)
3. 使用JWT
引入JWT的依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
创建生成token和验证token的工具类JWTUtils, 代码如下:
public class JWTUtils {
// JWT加密秘钥,自定义
private static final String jwtToken = "13suwbxsjxn!@#$%^&*!@$$";
public static String createToken(Long userId) {
// 自定义负载
Map<String, Object> clains = new HashMap<>();
clains.put("userId", userId);
// 生成JWT创建对象,自行设置需要的官方负载字段
JwtBuilder jwtBuilder = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, jwtToken)
.setClaims(clains)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000));
// 生成token
String token = jwtBuilder.compact();
return token;
}
public static Map<String, Object> checkToken(String token) {
try {
// 验证token,并返回负载中的数据
Jwt parse = Jwts.parser().setSigningKey(jwtToken).parse(token);
return (Map<String, Object>) parse.getBody();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
简单写个验证程序如下:
public static void main(String[] args) {
String token = createToken(123456776543123456L);
System.out.println("================生成的token==============" );
System.out.println(token);
System.out.println("================验证token================");
System.out.println(checkToken(token));
}
运行结果如图片所示: