JWT的使用场景
前后端分离项目(移动APP、小程序、H5)
JWT分为三部分:
1. header 头部
加密算法 使用base64编码格式 Alg:HS256
标准中注册的声明 (建议但不强制使用)
• iss: jwt签发者
• sub: jwt所面向的用户
• aud: 接收jwt的一方
• exp: jwt的过期时间,这个过期时间必须要大于签发时间
• nbf: 定义在什么时间之前,该jwt都是不可用的.
• iat: jwt的签发时间
• jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
2. payload
base64编码
payload中的数据无法被篡改,验证签名
3. verify signature(签名)
使用MD5加密,payload.toJSONString()+signingKey(盐值) 存放在服务器端
解密
JSONObject header = new JSONObject();
header.put("Alg", "HS256");
JSONObject payload = new JSONObject();
payload.put("name", "zhangsan");
payload.put("age", "23");
payload.put("address", "西安");
//base64 编码
String jwtHeader = Base64.getEncoder().encodeToString(header.toJSONString().getBytes());
String jwtPayload = Base64.getEncoder().encodeToString(payload.toJSONString().getBytes());
// 盐
String signKey = "amazing";
// sign签名
String signing = DigestUtils.md5Hex(payload.toJSONString() + signKey);
// 组成jwt
String jwt = jwtHeader + "." + jwtPayload + "." + signing;
System.out.println(jwt);
/* 解密 拿到一个jwt的操作
* 加双斜杠是转义字符 防止报错
*/
// 切割索引为1的是payload
String jwtPayload1 = jwt.split("\\.")[1];
// 签名
String jwtSign1 = jwt.split("\\.")[2];
String ss = DigestUtils.md5Hex(new String(Base64.getDecoder().decode(jwtPayload1.getBytes()),"UTF-8") + signKey);
System.out.println(ss.equals(jwtSign1));
JWT的优缺点
优点:
• 无需在服务器存放用户的数据,减轻服务器的压力
• 轻量级,json风格比较简单
• 跨语言
缺点
• JWT一旦生成后期无法修改(因为jwt生成的时候设定了有效期存放在客户端)
• 无法更改jwt有效期
• 无法销毁jwt(客户端清除cookie服务器还在)
• 建议时间设置短一点(30分钟-1天) 具体根据项目情况而定
JWT和Token的区别
JWT不需要依赖于服务器,将数据信息直接存放在客户端(浏览器)
Token是依赖于redis的,将数据存放在redis中 token想要销毁的话直接清除redis即可
Token存放value数据时比较安全的
JWT过期时间
如果从jwt中拿到的过期时间大于当前系统时间,就说明jwt已经过期了