Cookie、Session、Token三者的区别

背景:由于HTTP 协议是无状态的,为了应对交互式web的需求,cookie、session、token诞生。

Cookie

数据保存到用户端。看一个记录用户购物车商品的需求:

img

随着购物车内的商品越来越多,每次请求的 cookie 也越来越大,对后面的每个请求都会造成一个大的负担。

Session

用户数据保存在服务端,将sessionId保存到cookie中返回给前端,以后的每次请求都只需携带sessionId。

img

session问题:客户端请求后,通过负载均衡会将请求打到不同的服务端,进而找不到对应的session

解决方法:

  1. session 复制:保证每台服务端都有全部的session会话信息。由于同一个session保存了多份造成了数据冗余,对于节点多的情况造成整体的性能消耗也会很大。
  2. session粘连:通过配置ip_hash让相同 IP 的请求在负载均衡时都打到同一台机器上。但无法应对对应的机器挂了的情况。
  3. session 共享:将 session 保存在 redis等中间件中,请求到来时再去这些中间件取一下 session 。每个请求都要去 redis 取一下 session,多了一次内部连接带来的性能消耗,另外为了避免单点故障、保证 redis 的高可用,必须做集群。

Token

Token:一个加密的字符串,通过MD5等一些不可逆加密算法实现,可以保证唯一性。

JWT(Json Web Token):属于一种特殊的token,由三部分组成,它们之间用圆点(.)连接。

  • Header --> token的类型 + 签名算法
  • Payload --> 声明
  • Signature --> 签名部分,利用header中指定签名算法对编码过的header + 编码过的payload + 一个秘钥进行签名。例如:
    HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

JWT和Token的区别:主要体现在验证时是否需要查询数据库。对于客户端发送过来的普通token来说,服务端需要查询数据库检查记录是否存在、token的过期时间以及用户id是否匹配等进行token的验证。对于JWT,服务端会取出 token 中的 header + payload,根据密钥生成签名,然后再与发送过来的token 中的签名比对,如果成功则说明签名是合法的,即 token 是合法的。
另外由于payload 中保存着用户信息,所以拿到 token 后进行解析就可获取用户信息,避免了像 session 那样要从 redis 去取的开销。jwt可以保存在用户端的cookie或者localStorage中,当保存在localStorage 中时可以避免 CSRF 跨站请求伪造攻击。

JWT应用场景:

  1. 单点登录(SSO)在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。由于Cookie 跨站不能共享,使用 Cookie 实现单点登录就很复杂,但使用JWT只要在 header 中加上 token 即可完成所有跨域站点的认证。
  2. 移动端应用移动端应用通常是无状态的,而Session 基于服务器端的状态管理,如果使用 Session 进行身份认证,移动应用需要频繁地与服务器进行会话维护,增加了网络开销和复杂性;

JWT的缺点:

  1. 没办法主动失效:JWT 不能像 Session 一样被强制无效。

    • 将 JWT 存入数据库:将有效的 JWT 存入数据库中比如 Redis。如果需要让某个 JWT 失效就直接从 Redis 中删除这个 JWT 即可。但是,这样会导致每次使用 JWT 都要先从 Redis 中查询 JWT 是否存在的步骤,而且违背了 JWT 的无状态原则。

    • 黑名单机制:和上面的方式类似,使用内存数据库比如 Redis 维护一个黑名单,如果想让某个 JWT 失效的话就直接将这个 JWT 加入到 黑名单 即可。然后,每次使用 JWT 进行请求的话都会先判断这个 JWT 是否存在于黑名单中。

  2. JWT 的续签问题

    • 用户登录返回两个 JWT:第一个是 accessJWT:JWT 本身的过期时间比如半个小时,另外一个是 refreshJWT 它的过期时间更长一点比如为 1 天。客户端登录后,将 accessJWT 和 refreshJWT 保存在本地,每次访问将 accessJWT 传给服务端。服务端校验 accessJWT 的有效性,如果过期的话,就将 refreshJWT 传给服务端。如果有效,服务端就生成新的 accessJWT 给客户端。否则,客户端就重新登录即可。
  • 30
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值