JWT和session的区别

JWT和session的区别

这两种数据结构存储方式主要都是用来保存用户的一些信息,常见的是登录信息

session的存储

当 client通过用户名密码请求server并通过身份认证后,server就会生成身份认证相关的 session 数据,并且保存在内存或者内存数据库。并将对应的 sesssion_id返回给client,client会把保存session_id(可以加密)在cookie。此后client的所有请求都会附带该session_id,以确定server是否存在对应的session数据以及检验登录状态以及拥有什么权限,如果通过校验就该干嘛干嘛,否则重新登录。
前端退出的话就清cookie。后端强制前端重新认证的话就清或者修改session

  • 优势

    1. 和JWT对比,session能主动清除
    2. session的完整数据保存在服务器端,安全性更优保障
    3. 和cookie联合使用(session返回id给cookie存储在客户端),灵活,兼容性更高
  • 劣势

    1. 在跨域的情况下,使用session会很麻烦(可以多机器共享session,例如可以将session存储进数据库或者reids中)
    2. 基于cookie的机制容易被CSRF(模拟用户在客户端的数据来向server端发送请求)
    3. 查询session需要数据库方面的查询操作

JWT的存储方式

  • JSON Web Token 定义了一种由.分隔的数据结构,由三部分组成,分别是header,Payroad,Signature,完整结构Header.Payload.Signature
  • 字符串中每一段都是被 base64url 编码后的 JSON,其中 Payload 段可能被加密

JWT 的 Header 通常包含两个字段,分别是:typ(type) 和 alg(algorithm)

  • typ:token的类型,这里固定为 JWT
  • alg:使用的 hash 算法,例如:HMAC SHA256 或者 RSA

    1
    2
    3
    4
    {
    "alg": "HS256",
    "typ": "JWT"
    }

payroad

  • 真实存储我们需要传递的信息的部分,例如正常我们会存储些用户 ID、用户名之类的。此外,还包含一些例如发布人、过期日期等的元数据
  • 一般使用Base64UrlEncoder进行加密数据

signature

  • 对header和payroad部分加密,保证token传输过程中没有没篡改
  • 除了 Header 和 Payload 之外,还多了一个密钥字段

    1
    Signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

工作方式

  1. 前端发起post请求,发送用户名和密码到server
  2. 后端核对成功,组装用户id等数据到payroad,加密header和payroad后签名,返回给前端
  3. 前端保存JWT数据到localStorage或sessionStorage,退出登录删除该数据
  4. 每次请求将jwt放在HTTP请求的HEADER-Authorization中,防止xss和xsrf攻击
  5. 后端验证JWT数据,返回结果

优势

  1. 扩展性更强

    • 随着应用程序的扩大和用户数量的增加,你必将开始水平或垂直扩展。session数据通过文件或数据库存储在服务器的内存中。在水平扩展方案中,你必须开始复制服务器数据,你必须创建一个独立的中央session存储系统
    • 用JWT是无缝的;由于基于token的身份验证是无状态的,所以不需要在session中存储用户信息。我们的应用程序可以轻松扩展,因为我们可以使用token从不同的服务器访问资源,而不用担心用户是否真的登录到某台服务器上。你也可以节省成本,因为你不需要专门的服务器来存储session
  2. 安全性更高

    • JWT签名旨在防止在客户端被篡改,但也可以对其进行加密,以确保token携带的claim 非常安全
  3. 下游的服务
    • 现代web应用程序的另一种常见模式是,它们通常依赖于下游服务。例如,在原始请求被解析之前,对主应用服务器的调用可能会向下游服务器发出请求。这里的问题是,cookie不能很方便地流到下游服务器,也不能告诉这些服务器关于用户的身份验证状态。由于每个服务器都有自己的cookie方案,所以阻力很大,并且连接它们也是困难的
  4. 对restful api的架构表现更好
    • RESTful API的原则之一是它应该是无状态的,这意味着当发出请求时,总会返回带有参数的响应,不会产生附加影响。用户的认证状态引入这种附加影响,这破坏了这一原则。保持API无状态,不产生附加影响,意味着维护和调试变得更加容易
    • 由一个服务器提供API,而实际应用程序从另一个服务器调用它的模式是很常见的。为了实现这一点,我们需要启用跨域资源共享(CORS)。Cookie只能用于其发起的域,相对于应用程序,对不同域的API来说,帮助不大。在这种情况下使用JWT进行身份验证可以确保RESTful API是无状态的,你也不用担心API或应用程序由谁提供服务

劣势

  1. 性能差
    • 当从客户端向服务器发出请求时,如果大量数据在JWT内进行编码,则每个HTTP请求都会产生大量的开销。然而,在会话中,只有少量的开销,因为SESSION ID实际上非常小
  2. 时效性差
    • 无状态JWT的实效性相比session太差,只有等到过期才可销毁,而session则可手动销毁
    • 用户发现账号被异地登录,然后修改密码,此时token还未过期,异地的账号一样可以进行操作包括修改密码
    • 将JWT生成的token存入到redis或者数据库中,当用户登出或作出其他想要让token失效的举动,可通过删除token在数据库或者redis里面的对应关系来解决这个问题。

session、cookie、sessionStorage、localstorage的区别

  • session: 主要存放在服务器端,相对安全
  • cookie: 可设置有效时间,默认是关闭浏览器后失效,主要存放在客户端,并且不是很安全,可存储大小约为4kb
  • sessionStorage: 仅在当前会话下有效,关闭页面或浏览器后被清除
  • localstorage: 除非被清除,否则永久保存