代码里面, 客户端和服务端之间的交互, 用了jwt, 从代码里面看到, 服务端对客户端之间的各种 加密验证签名等(不一一介绍了) , 最后还生成了jwt , 关于jwt, 在网上找到了一篇很好的博客, 基本概念写的很详细, 大家可以点击链接进去看
https://blog.csdn.net/weixin_42139757/article/details/80689234 作者:GhostSugar
以下内容是我从这篇博客里面复制过来的.
1.背景介绍
什么是JWT
JWT(JSON WEB TOKEN):JSON网络令牌,JWT是一个轻便的安全跨平台传输格式,定义了一个紧凑的自包含的方式在不同实体之间安全传输信息(JSON格式)。它是在Web环境下两个实体之间传输数据的一项标准。实际上传输的就是一个字符串。广义上讲JWT是一个标准的名称;狭义上JWT指的就是用来传递的那个token字符串
JWT用来做什么?怎么来的?
由于http协议是无状态的,所以客户端每次访问都是新的请求。这样每次请求都需要验证身份,传统方式是用session+cookie来记录/传输用户信息,而JWT就是更安全方便的方式。它的特点就是简洁,紧凑和自包含,而且不占空间,传输速度快,而且有利于多端分离,接口的交互等等
JWT是一种Token规范,主要面向的还是登录、验证和授权方向,当然也可以用只来传递信息。一般都是存在header里,也可以存在cookie里。
-
紧凑: 意味着这个字符串很小,甚至可以通过URL参数,POSTparameter中以Http Header的方式传输。
-
自包含:传输的字符串包含很多信息,别人拿到以后就不需要再多次访问数据库获取信息,而且通过其中的信息就可以知道加密类型和方式,当然解密需要公钥和密钥。
应用场景:认证和授权,认证解决[你是谁]的问题,授权解决了[你能做什么]的问题 一次性验证,邮件验证
注册激活
登录验证,长期未登录激活
应用授权
单点登录
什么是TOKEN
Token是服务器签发的一串加密字符串,是为了给客户端重复访问的一个令牌,作用是为了证明请求者(客户端)的身份,保持用户长期保持登录状态。
JWT和TOKEN的关系
JWT就是TOKEN的一种载体,或者说JWT是一种标准,而Token是一个概念,而JWT就是这个概念执行的一种规范,通俗点说token就是一串字符串,jwt就是加上类型,信息等数据再加密包装一下成为一个新的token。
最直观的区别就是不使用JWT的token需要查询数据库来验证,而使用JWT可以不用对数据库进行操作,因为它本身包含了可自定义的信息
JWT是所有语言通用的
其实sessionID储存也算是一种token
- JWT是所有语言通用的
- 其实sessionID储存也算是一种token
2.知识剖析
JWT的数据结构以及签发的过程
JWT由三部分构成:header(头部)、payload(载荷)和signature(签名)。
Header 头部信息:指定类型和算法
Payload 荷载信息:存放Claims声明信息
Signature 签名:把前两者对应的Json结构进行base64url编码之后的字符串拼接起来和密钥放一起加密后的签名
组成方式为 header.payload.signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpc3MiOiLlvKDlvLoiLCJuYW1lIjoiNzg5IiwiZXhwIjoxNTI4MzY0MjU5LCJpYXQiOjE1MjgzNjMwNTl9.574koY-c9SqMNNzfvAWQuKEnimWeZAcoFQ5XudNWF3o
Header的结构
* type 声明类型
* algorithm 声明加密算法
格式: {“typ”: “JWT”,“alg”: “HS256”}
payload的结构
* 声明信息
payload用来承载要传递的数据,它的json结构实际上是对JWT要传递的数据的声明,这些声明被JWT标准称为claims(声明),它的每个属性键值对其实就是一个claim,JWT常用的有两种声明,一种是Reserved claims(保留声明),也就是JWT规定的标准声明。
一种是Private claims(自定义声明),我们在这里定义要传递的信息
还有一种是public claims(公共声明),这个目前没用到。
格式: {"name": "value","id": "value2"}
1
标准声明(JWT保留声明)
•iss(Issuser):代表这个JWT的签发主体;
•sub(Subject):代表这个JWT的主体,即它的所有人;
•aud(Audience):代表这个JWT的接收对象;
•exp(Expiration time):是一个时间戳,代表这个JWT的过期时间;
•nbf(Not Before):是一个时间戳,代表这个JWT生效的开始时间,意味着在这个时间之前验证JWT是会失败的;
•iat(Issued at):是一个时间戳,代表这个JWT的签发时间;
•jti(JWT ID):是JWT的唯一标识。
signature
* 签名
把header和payload对应的json结构进行base64url编码之后得到的字符串用点号拼接起来,然后根据header里面alg指定的签名算法生成出来的,然后添加自己设定的key进行加密签名
添加:
.sign(Algorithm.HMAC256(Key))
在线加密解密:http://tool.oschina.net/encrypt?type=3
工具
auth0 OAuth2.0 JWTUtil jsonwebtoken
3.常见问题
如何验证
当接收方接收到一个JWT的时候,首先要对这个JWT的完整性进行验证,这个就是签名认证。它验证的方法其实很简单,只要把header使用base64url解码以后就知道签发者用什么算法做的签名,然后用这个算法对header和payload加密一下,再比较这个签名是否和JWT本身包含的signature是否完全相同,只要不同就可以认为这个JWT是被篡改过的。所以接收方生成签名的时候必须使用跟JWT发送方相同的密钥。
再次就是验证payload里的部分,比如是否过期,还有自定义的信息是否相同,加上已经前面验证的signature,这样就保证了这个签名的有效性
互斥登录/修改密码后登录的问题
场景:用户在多个设备或者其它浏览器/IP登录以后或者修改密码以后,那其它的设备就需要自动退出登录
用户修改密码之后签发一个新的token来覆盖之前的。但是之前的token只要在失效之前仍然是可以验证并且登录的
用户手动退出的时候也是需要token失效的,这就需要退出的时候直接清除或者覆盖客户端保存的token。同上,之前的token仍然有效,所以token的时间不能太长
设置黑名单,在签发新token的时候把之前未过期的token加入黑名单使之失效。但是这样就需要储存token,而jwt的优点就是不需要储存空间。
续签
场景:需要用户长期登录的应用,比如用你开发需要用户保持登录的应用,在使用token的时候保证用户体验不需要频繁登录操作,又要保证用户在一段时间之后登录过期重新登录,主要是一个用户体验和用户信息安全的问题。这个时候又要求token不能过长,只能通过续签来保持登录状态
又或者说用户登录的时候你需要获取用户在社交网站的信息,就需要获取社交网站授权的token,这也需要续签,不过这是向社交网站续签。这里后面说。
何时续签:
1.每次请求刷新 每次请求直接覆盖签发新的token
2.记录时间定时刷新 设置一个定时器,记录签发时间,然后到过期的时候签发新的
3.临期时刷新 访问的时候对比时间,如果即将过期就立即刷新。
4.过期后续签,这样设置过期时间的意义就在于如果token被盗取后黑客登录也需要续签,这样用户再次登录客户端就会发现用户登录异常。而且每次获取的token都是新的,旧的只能获取一次续签的机会,也就说如果用户续签以后之前的token就不能再续签了。
5.jwt-autorefresh(JWT自动刷新)(有限制条件,在客户端定时刷新)
4.~~~~~~
5~~~~~~~
6.参考文献
JWT实现token-based会话管理 : https://www.cnblogs.com/lyzg/p/6028341.html
RFC 7519 : https://tools.ietf.org/html/rfc7519
RFC : https://baike.baidu.com/item/RFC/1840?fr=aladdin
auth0:https://auth0.com/docs/tokens/refresh-token/current
oauth2 : https://oauth.net/2/
7.更多讨论
A:JWT有什么不好的地方?
Q:不好的地方就是JWT等于说是泼出去的水,发出去的令牌,不可更改,只要有效期内就可以永使用
A: JWT安全性如何?
Q: 这也是JWT最重要的一点,它的出现就是为了免登陆或者权限控制,所以它的安全性至关重要。所以它虽然是一直加密的,但是安全性总是建立在相对性之上的。所以只能说一定程度上是安全的。
A: JWT如何存放?
Q: JWT不需要存放,或者说存放在客户端那里。服务端只需要有解密算法就可以判断当前的JWT是不是有效的。