jwt
JWT(json web token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。
适用于分布式站点的单点登录(SSO)场景。
JWT如何获取访问令牌(token)并用于访问资源(API)流程:
1、应用端向权限服务器请求授权;
2、权限服务器授权成功向应用端返回一个访问令牌(token);
3、应用端使用访问令牌(token)访问受保护的资源(如API)。
jwt和token的区别:
- token依赖于Redis查询数据信息,token存放value数据比较安全的。
- Jwt 不需要依赖于服务端,将数据信息内容直接存放在客户端(浏览器)
jwt的构成
第一部分我们称它为头部(header)
第二部分我们称其为载荷(payload)
第三部分是签证(signature)
头部(header)
jwt的头部承载两部分信息:
声明类型,这里是jwt
声明加密的算法 通常直接使用 HMAC SHA256
然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.
token的头是固定的
载荷(payload)
携带一些用户信息。如{“userId” : “1” ,“username” : “zs”}
- 标准中注册的声明
- 公共的声明
- 私有的声明
标准中注册的声明
iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
公共的声明
一般添加用户的相关信息或其他业务需要的必要信息。
私有的声明
私有声明是提供者和消费者所共同定义的声明,
签证(signature)
防止token被篡改,确保安全性。
这个签证信息由三部分组成:
header (base64后的)
payload (base64后的)
secret
base64加密后的header和base64加密后的payload连接组成的字符串
。然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。
jwt的优缺点
优点:
- 无需在服务器存放用户的数据,减轻服务端压力。
- 轻量级、json风格比较简单。
- 跨语言。
缺点:
jwt一旦生成后就无法修改
- 无法更新jwt有效期(无法提前过期)
- 无法销毁一个jwt
建议:
浏览器cookie删除
过期时间设置短一些。
手写一个jwt加密
public class JWTDemo01 {
public static void main(String[] args) {
//手写一个jwt案例
/**
* 头部
* payLoad
* 验证签名
*/
//header
JSONObject header = new JSONObject();
header.put("Alg","HS256");
//playLoad
JSONObject payLoad = new JSONObject();
payLoad.put("username","sparks");
payLoad.put("userAge","20");
//base64 对数据进行编码
String jwtHeader = Base64.getEncoder().encodeToString(header.toJSONString().getBytes());
String jwtPayLoad = Base64.getEncoder().encodeToString(header.toJSONString().getBytes());
//签名 后面加盐
String signKey = "sparks";
String sign = DigestUtils.md5Hex(payLoad.toJSONString() + signKey);
String jwt = jwtHeader + "." + jwtPayLoad + "." + sign;
System.out.println(jwt);
}
}
jwt获取令牌访问资源流程
JWT如何获取访问令牌(token)并用于访问资源(API)流程:
- 用户使用用户名密码来请求服务器
- 服务器进行验证用户的信息
- 服务器通过验证发送给用户一个token
- 客户端存储token,并在每次请求时附送上这个token值
- 服务端验证token值,并返回数据