jwt超时刷新策略
<h1>jwt</h1>
<h2>1 jwt是什么</h2>
<p>jwt全称json web token,这是一种认证机制,让后台知道请求是来自于受信的客户端。</p>
<h2>2 jwt的组成</h2>
<p>jwt由三部分组成:</p>
<ul>
<li>header,包含了两部分,token类型和采用的加密算法。它会使用 Base64 编码组成 JWT 结构的第一部分。
<pre><code class="language-json">{
"alg": "HS256",
"typ": "JWT"
}</code></pre></li>
<li>payload,存放信息的地方了,你可以把用户 ID 等信息放在这里。常用的由 iss(签发者),exp(过期时间)
,sub(主题),aud(接收方),iat(签发时间)等组成。同样的,它会使用 Base64 编码组成 JWT 结构
的第二部分。
<pre><code class="language-json">{
"iss": "lion1ou JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
"sub": "lion1ou@163.com"
}</code></pre></li>
<li>signature,前面两部分都是使用 Base64 进行编码的,即前端可以解开知道里面的信息。Signature 需
要使用编码后的 header 和 payload 以及我们提供的一个密钥,然后使用 header 中指定的签名算法
(HS256)进行签名。签名的作用是保证 JWT 没有被篡改过。三个部分通过.连接在一起就是我们的 JWT 了。</li>
</ul>
<p>实际的jwt串如下:
<img src="https://s2.ax1x.com/2019/12/17/QIHWJx.png" alt="实际的jwt" /></p>
<p>它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展示,
将它写成了几行。</p>
<h2>3 签名的目的</h2>
<p>最后一步签名的过程,实际上是对头部以及负载内容进行签名,防止内容被窜改。如果有人对头部以及负载
的内容解码之后进行修改,再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断
出新的头部和负载形成的签名和JWT附带上的签名是不一样的。如果要对新的头部和负载进行签名,在不知道
服务器加密时用的密钥的话,得出来的签名也是不一样的。</p>
<h2>4 信息暴露</h2>
<p>在这里大家一定会问一个问题:Base64是一种编码,是可逆的,那么我的信息不就被暴露了吗?</p>
<p>是的。所以,在JWT中,不应该在负载里面加入任何敏感的数据。在上面的例子中,我们传输的是用户的
User ID。这个值实际上不是什么敏感内容,一般情况下被知道也是安全的。但是像密码这样的内容就不能被
放在JWT中了。如果将用户的密码放在了JWT中,那么怀有恶意的第三方通过Base64解码就能很快地知道你的
密码了。</p>
<p>因此JWT适合用于向Web应用传递一些非敏感信息。JWT还经常用于设计用户认证和授权系统,甚至实现Web应
用的单点登录。</p>
<h2>5 jwt认证流程</h2>
<p><img src="https://s2.ax1x.com/2019/12/17/QIHRF1.png" alt="token认证流程" />
jwt可以实现无状态的服务,服务端完全不用保存token信息,把token分散到客户端去存储。但是,jwt一经
签发,在有效期内任何人获取到jwt,都可以用来访问服务端。所以,一般使用的时候还是会在服务端保存
token信息。</p>
<h2>6 jwt超时刷新策略</h2>
<p>对于登录的用户签发其对应的jwt,我们在jwt设置他的固定有效期时间,在有效期内用户携带jwt访问没问题
,当过有效期后jwt失效,用户需要重新登录获取新的jwt。这个体验不太好,好的体验应该是:活跃的用户
应该在无感知的情况下在jwt失效后获取到新的jwt,携带这个新的jwt进行访问,而长时间不活跃的用户应
该在jwt失效后需要进行重新的登录认证。
<img src="https://s2.ax1x.com/2019/12/17/QIH4SK.png" alt="jwt超时刷新策略" />
这里会出现一个问题,在同一页面下,如果同时有多个请求几乎同时发起,在第一个请求刷新了token并更改了
时间戳之后,后续的请求在验证时间戳时会失败。这里可以解决的办法有:</p>
<ul>
<li>前端过滤,在刷新token的时候不允许同一时刻发出多个refreshToken的请求,多余的过滤。</li>
<li>服务端加锁,只允许一个请求刷新token,其它的请求由于在濒临有效时间内,可以直接放行。</li>
</ul>