jwt 认证

2022-04-15 15:56:21 浏览数 (1)

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。

1. 基于token的认证

当用户成功登录系统并成功验证有效之后,服务器会利用某种机制产生一个token字符串,这个token中可以包含很多信息,例如来源IP,过期时间,用户信息等, 把这个字符串下发给客户端,客户端在之后的每次请求中都携带着这个token,携带方式其实很自由,无论是cookie方式还是其他方式都可以。当服务端收到请求,取出token进行验证(可以验证来源ip,过期时间等信息),如果合法则允许进行操作。

基于token的验证方式它有什么优点吗?

  1. 支持跨域访问,Cookie是不允许跨域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.
  2. 无状态:Token机制在服务端不需要存储session信息,因为Token自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.
  3. 解耦 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.
  4. 适用性更广:只要是支持http协议的客户端,就可以使用token认证。
  5. 服务端只需要验证token的安全,不必再去获取登录用户信息,因为用户的登录信息已经在token信息中。
  6. 基于标准化:你的API可以采用标准化的 JSON Web Token (JWT).

那基于token的认证方式有哪些缺点呢?

  1. 网络传输的数据量增大:由于token中存储了大量的用户和安全相关的信息,所以比单纯的cookie信息(例如session_id)要大很多,传输过程中需要消耗更多流量,占用更多带宽,
  2. 和所有的客户端认证方式一样,如果想要在服务端控制token的注销有难度,而且也很难解决客户端的劫持问题。
  3. 由于token信息在服务端增加了一次验证数据完整性的操作,所以比session的认证方式增加了cpu的开销。

但是整体来看,基于token的认证方式还是比session和cookie方式要有很大优势。在所知的token认证中,jwt是一种优秀的解决方案。

2. jwt认证

JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。中间用点(.)分隔成三个部分。注意JWT 内部是没有换行的。

2.1 头部

header典型的由两部分组成:token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)。

代码语言:javascript复制
{  "alg": "HS256",  "typ": "JWT"}

2.2 Payload

Payload 部分也是一个JSON对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。

代码语言:javascript复制
iss (issuer):签发人exp (expiration time):过期时间sub (subject):主题aud (audience):受众nbf (Not Before):生效时间iat (Issued At):签发时间jti (JWT ID):编号

除了以上字段之外,你完全可以添加自己想要的任何字段,这里还是提醒一下,由于jwt的标准,信息是不加密的,所以一些敏感信息最好不要添加到json里面

代码语言:javascript复制
{    "Name":"菜菜",    "Age":18}

2.3 Signature

为了得到签名部分,你必须有编码过的header、编码过的payload、一个秘钥(这个秘钥只有服务端知道),签名算法是header中指定的那个,然后对它们签名即可。

代码语言:javascript复制
HMACSHA256(base64UrlEncode(header)   "."   base64UrlEncode(payload), secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用”点”(.)分隔,就可以返回给用户。需要提醒一下:base64是一种编码方式,并非加密方式。

3. jwt使用

3.1 流程

  1. 客户端携带用户的登录凭证(一般为用户名密码)提交请求
  2. 服务端收到登录请求,验证凭证正确性,如果正确则按照协议规定生成token信息,经过签名并返回给客户端
  3. 客户端收到token信息,可以保存在cookie或者其他地方,以后每次请求的时候都携带上token信息
  4. 业务服务器收到请求,验证token的正确性,如果正确则进行下一步操作

3.2 交互

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。 此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

代码语言:javascript复制
Authorization: Bearer <token>fetch('api/user/1', {  headers: {    'Authorization': 'Bearer '   token  }})

3.3 特点

(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。 (2)JWT 不加密的情况下,不能将秘密数据写入 JWT。 (3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。 (4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。 (5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。 (6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

3.4 问题

  1. 用户登出,如何设置token无效?
    • 用户登出,浏览器端丢弃token
    • 使用redis数据库,用户登出,从redis中删除对应的token,请求访问时,需要从redis库中取出对应的token,若没有,则表明已经登出
  2. 两个不同的设备,一个设备登出,另外一个设备如何处理?
    • 服务器维护一个清单(记录该账号是否已经签发token),这样又回到session的老路了
    • 每一个设备与用户生成唯一的key,保存在redis中,即设备1的用户登出,只删除对应的token,设备2的token仍然存在
    • 服务器端维护一个版本号,相同用户不同设备登入,版本号加1,这样保持key的唯一性(和上面差不多)

source: //www.liuvv.com/p/722ed7e7.html

0 人点赞