Token和Refresh Token

一、Token

在计算机身份认证中代表令牌,在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。

1.1、Jwt简介

JWT(JSON Web Token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。

它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证;应用场景如用户登录。

1.2、为什么有Jwt

目前主流的Web开发模式有两种:

  • 基于服务端渲染的传统Web开发模式
  • 基于前后端分离的新型Web开发模式

对于这两种开发模式的身份认证,服务端渲染推荐使用 Session认证机制,前后端分离推荐使用JWT认证机制。

对于传统的session认证,因为HTTP是无协议的,为了记住用户状态,服务器在用户第一次访问时会返回一个cookie同时服务端保存一个对应的session,但是这种基于session的认证使应用本身很难得到扩展,随着不同客户端用户的增加,大量session会话的创建对服务器是一个巨大的开销;

同时,当服务端为集群时,用户登录其中一台服务器,会将session保存在该服务器的内存中,
只有再次访问这台服务器才能拿到授权资源。

另外session认证机制依赖Cookie,但是Cookie默认不支持跨域访问,所以,当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域Session认证。这就有了JWT的出现,流程上是这样的:

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据

在这里插入图片描述

1.3、Jwt Token结构

JWT由三部分构成,第一部分我们称它为头部(header),第二部分我们称其为载荷(payload),第三部分是签证(signature)。

  • header:Header通常由两部分组成:令牌的类型,即JWT。和常用的散列算法,如HMAC SHA256或RSA。

{
“typ”: “JWT”,
“alg”: “HS256”
}
由上可知,该token使用HS256加密算法,将头部进行base64加密(该加密是可以对称解密的),构成了第一部分:
eyJhbGciOiJIUzI1NiJ91

  • Playload:载荷就是存放有效信息的地方,这些有效信息包含三个部分

    1、 Registered claims(注册声明): 这些是一组预先定义的声明,它们不是强制性的,但推荐使用,以提供一组有用的,可互操作的声明。 其中一些是:iss(发行者),exp(到期时间),sub(主题),aud(受众)等
    2、Public claims (公开声明): 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密。
    3、Private claims(私有声明): 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

{
“iss”: “Online JWT Builder”,
“iat”: 1416797419,
“exp”: 1448333419,
…….
“userid”:10001
}
有效载荷中存放了token的签发者(iss)、签发时间(iat)、过期时间(exp)等以及一些我们需要写进token中的信息。然后将其进行base64加密,得到Jwt的第二部分:
eyJ1c2VyaWQiOjB91

  • Signature:这个部分需要base64加密后的header和base64加密后的payload使用,连接组成的字符串(头部在前),然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

例如头部与载体加密拼接后的字符串为eyJhbGciOiJIUzI1NiJ91.eyJ1c2VyaWQiOjB91再次利用加密算法(HS256)与自定义的密钥(secret)加密得到签名部分字符:
rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
将上面三个方法生成的字符串再次拼接就得到了完整的Token:
eyJhbGciOiJIUzI1NiJ91.eyJ1c2VyaWQiOjB91.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token

1.4、JWT的优缺点

  • 优点
    1、因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
    2、payload可以在自身存储一些其他业务逻辑所必要的非敏感信息。
    3、它不需要在服务端保存会话信息, 所以它易于应用的扩展

  • 缺点
    1、安全性:由于JWT的payload是使用Base64编码的,并没有加密,因此JWT中不能存储敏感数据。而Session的信息是存在服务端的,相对来说更安全。
    2、一次性:无状态是JWT的特点,但也导致了这个问题,JWT是一次性的。想修改里面的内容,就必须签发一个新的JWT。即缺陷是一旦下发,服务后台无法拒绝携带该jwt的请求(如踢除用户)

二、Refresh Token

Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位,而Token的playload部分一般会存储相关的过期时间,一旦Token过期就会被拦截,因此如何设置Token刷新机制也是一个重点。

过长的过期时间会让系统有长期暴露在接口的风险,理论上过期时间越短越好,但是过短的时间明显会带来不好的用户体验。那么我们可以考虑使用Refresh Token刷新,一旦 Token 过期,就反馈给前端,前端使用 Refresh Token 申请一个全新 Token 继续使用。

这种方案中,服务端只需要在客户端请求更新 Token 的时候对 Refresh Token 的有效性进行一次检查,大大减少了更新有效期的操作,也就避免了频繁读写。

2.1、实现原理

前端第一次发起请求时,后端准备两个 token,一个有效时间较短的作为认证 token(token),一个有效时间较长的作为刷新 token(refreshToken),返回给前端。

前端拿到两个 token 后,把它们都存储在 localStorage 中,后面再次发起请求时携带两个token:

  • token 未过期时,可以正常请求。
  • token 过期了,refreshToken 未过期,请求后端的刷新token接口对两个token进行更新并返回给前端。
  • token 和 refreshToken 均过期了,则用户必须重新登录。

2.2、代码实现

demo:
Token refresh的实现

猜你喜欢

转载自blog.csdn.net/weixin_44153131/article/details/129034135