初次了解JWT,高手勿喷。
什么是JWTJson web token (JWT)?
是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
个人见解是基于Token的身份验证用来替代传统的cookie+session身份验证方法中的session。
为什么session不好呢?
是因为每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。还有当服务器为集群多机的情况下,需要复制sessionid,在多台集群机器之间共享。
为什么cookie不好呢?
是因为如果我们的页面出现了 XSS 漏洞,由于 cookie 可以被 JavaScript 读取,XSS 漏洞会导致cookie泄露,而作为后端识别用户的标识,cookie 的泄露意味着用户信息不再安全。
既然传统的方法不安全那就看看jwt吧
JWT 组成
一个jwt实际上就是一个字符串,它由三部分组成,头部、载荷与签名,这三个部分都是json格式。前面两部分都是使用 Base64 进行编码的,而Signature 需要使用编码后的 header 和 payload 以及我们提供的一个密钥,然后使用 header 中指定的签名算法(HS256)进行签名。签名的作用是保证 JWT 没有被篡改过。
然后拼接起来,中间用 . 分隔。
首先是Header 头部
{
"alg": "HS256",
"typ": "JWT"
}
alg:是采用的加密算法
typ:其类型
这个头部表明这是一个JWT,并且我们所用的签名算法是HS256算法。
Base64 编码后:ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9
然后是Payload 负载又称有效荷载
JWT 规定了7个官方字段,供选用。
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
而我就用了5个(注意:由于base64编码是可逆的,请不要把重要信息放在里面,可以放下些userId等主键信息)
{
"iss": "test-jwt",
"iat": 1560521498,
"exp": 1560523298,
"aud": "www.example.com",
"sub": "test@qq.com"
}
Base64 编码后:ewogICAgImlzcyI6ICJ0ZXN0LWp3dCIsCiAgICAiaWF0IjogMTU2MDUyMTQ5OCwKICAgICJleHAiOiAxNTYwNTIzMjk4LAogICAgImF1ZCI6ICJ3d3cuZXhhbXBsZS5jb20iLAogICAgInN1YiI6ICJ0ZXN0QHFxLmNvbSIKfQ==
最后是Signature(签名)
header和payload是需要base编码后拼接在通过密钥secret通过哈希加密HMACSHA256生成签名
var signature=HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret)
HMACSHA256编码后:5ad864059af3e589f0d1ae4081c685550158bbb2653e3f0f574de44432ef4cf2
这样完整的token就是ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9.ewogICAgImlzcyI6ICJ0ZXN0LWp3dCIsCiAgICAiaWF0IjogMTU2MDUyMTQ5OCwKICAgICJleHAiOiAxNTYwNTIzMjk4LAogICAgImF1ZCI6ICJ3d3cuZXhhbXBsZS5jb20iLAogICAgInN1YiI6ICJ0ZXN0QHFxLmNvbSIKfQ==.5ad864059af3e589f0d1ae4081c685550158bbb2653e3f0f574de44432ef4cf2
客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程
是这样的:
客户端使用用户名、密码请求登录
服务端收到请求,去验证用户名、密码
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户
端返回请求的数据
这里有java代码写的jwt代码仅供参考:https://download.csdn.net/download/qq_39552993/11239870
考虑到要有些人积分不够,也可以看看这位大佬的demo:https://www.cnblogs.com/jimisun/p/9482439.html (其实跟我的上传的代码差不多的)