登录授权方案:JSON Web Tokens (JWT)

登录授权方案:JSON Web Tokens (JWT)

JWT官方文档:https://jwt.io/introduction


1.简介:

JWT 即 json web tokens,通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输,在数据传输过程中还可以完成数据加密、签名等相关处理。可用于登录授权或者其他服务之前的信息交换;JWT本质就是一个字符串,它是一个开放标准(rfc7519),定义了一种紧凑的、自包含的方式;它是无状态的,去中心化的;


2.JWT校验流程:

在这里插入图片描述

  • 1.前端输入账号密码后,请求授权服务;
  • 2.授权服务返回对应的token,前端保存在 localStorage
  • 3.每次请求,前端在请求头中携带token与业务接口进行交互,业务接口根据加密规则进行校验,获取token中的信息;

因此,jwt是无状态的,并且具有去中心化的特性,后端每次只根据规则去校验token,不用每次都去请求数据库/redis,减少了token校验的查询这一层;


3.JWT的组成结构

由三部分组成,这些部分由 . 分隔,分别是:

  • Header
  • Payload
  • Signature

由这三部分拼接为: Header.Payload.Signature 的形式

3.1 关于header

Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子:

{
    "alg": "HS256",
    "typ": "JWT"
}

alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);
typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT

Header会被Base64Url编码为JWT的第一部分,即:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

3.2 关于Payload

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据,它包含三部分:

JWT 提供了7个官方字段,可选用:

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):JWT接收者
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

除了官方字段,你还可以在这个部分定义私有字段,如:

{
  "uid": 10, 
  "username": "test", 
  "scopes": [ "admin", "user" ] 
}

我们挑选官方的 iat,exp,再加上我们的自定义字段,如下:

{ "iat": 1593955943, 
  "exp": 1593955973, 
  "uid": 10, 
  "username": "test", 
  "scopes": [ "admin", "user" ] 
}

Payload会被Base64Url编码为JWT的第二部分,即:

eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1OTM5NTU5NDMsInVpZCI6MTAsImV4cCI6MTU5Mzk1NTk3Mywic2NvcGVzIjpbImFkbWluIiwidXNlciJdfQ

3.3 关于Signature

Signature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给别人。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式进行签名:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

算出签名后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用 . 分隔,就可以返回给用户,样式如下:

“eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1OTM5NTU5NDMsInVpZCI6MTAsImV4cCI6MTU5Mzk1NTk3Mywic2NvcGVzIjpbImFkbWluIiwidXNlciJdfQ.VHpxmxKVKpsn2Iytqc_6Z1U1NtiX3EgVki4PmA-J3Pg”


4.JWT 特点总结:

(1)JWT 是去中心化的, 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

(2)JWT 是无状态的, 缺点在于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

(3)JWT 默认是不加密,所以JWT 不加密的情况下,不要将敏感信息写入 JWT,生成原始 Token 以后,我们也可以用密钥再次进行加密。

(4)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。


5.常见问题及对应的解决方案(仅供参考):

问题1: 因为一旦 JWT 签发了,在到期之前就会始终有效当用户退出登录,或被冻结,或者修改密码怎么处理?

黑名单机制,使用内存数据库,如 Redis, 维护一个黑名单,如果想让某个 JWT 失效的话

就直接将这个 JWT 加入到 黑名单 即可。然后,每次使用 JWT 进行请求的话都会先判断这个 JWT 是否

存在于黑名单中。虽然此方案违背了 JWT 的无状态原则,但是一般实际项目中通常还是会使用这个方法。

.
问题2: JWT 的续签问题,JWT 有效期一般都建议设置的不太长,那么 JWT 过期后如何认证,如何实现动态刷新 JWT,避免用户经常需要重新登录?

答: 用户登录后可返回两个 JWT,第一个是 accessJWT ,它的过期时间是 JWT 本身的过期时

间,比如1个小时,另外一个是 refreshJWT 它的过期时间更长一点比如为 1 天。

客户端登录后,将 accessJWT 和 refreshJWT 保存在本地,每次访问将 accessJWT 传给服务端。服务

端校验 accessJWT 的有效性,如果过期的话,再把 refreshJWT 传给服务端。如果此时refreshJWT 有

效,服务端就生成新的 accessJWT 给客户端。否则,客户端就需要重新登录。

还有需要注意的是:

  • 1.用户注销的时候需要同时保证两个 JWT 都无效;
  • 2.如果是accessJWT过期之后,再去重新请求获取 accessJWT的过程中会有短暂 token 不可用的情况,可以通过在客户端设置定时器,当 accessJWT 快过期的时候,提前去通过 refreshJWT 获取新的accessJWT。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值