深入理解有状态和无状态以及JWT和Session

1.概念

参考链接:https://blog.csdn.net/Jmilk/article/details/50461577

  • 基于状态的Web服务
    在基于状态的Web服务中,Client与Server交互的信息(如:用户登录状态)会保存在Server的Session中。再这样的前提下,Client中的用户请求只能被保存有此用户相关状态信息的服务器所接受和理解,这也就意味着在基于状态的Web系统中的Server无法对用户请求进行负载均衡等自由的调度(一个Client请求只能由一个指定的Server处理)。同时这也会导致另外一个容错性的问题,如果指定的Server在Client的用户发出请求的过程中宕机,那么此用户最近的所有交互操作将无法被转移至别的Server上,即此请求将无效化。

  • 基于无状态的Web服务
    在无状态的Web服务中,每一个Web请求都必须是独立的,请求之间是完全分离的。Server没有保存Client的状态信息,所以Client发送的请求必须包含有能够让服务器理解请求的全部信息,包括自己的状态信息。使得一个Client的Web请求能够被任何可用的Server应答,从而将Web系统扩展到大量的Client中。

2.Session和Jwt

上面说了,有状态和无状态两种web服务,他们分别所对应的技术为session和jwt。
参考链接:https://www.cnblogs.com/yuanrw/p/10089796.html
下面只总结各自的优缺点,以及适用场景:

  • session:
    • 缺点
    1. 需要从内存或者数据库里面取数据,进行验证,相对jwt来说更耗时。
    2. 扩展性差,对于分布式应用,需要实现session数据共享。比如,当使用分布式的情况下,可能由于负载均衡的策略,导致访问到了不同的服务器,所以得让用户登录时的seesion状态要共享到其他服务器(其数据库)上。
    • 优点
    1. 安全,数据存储在服务器端
    2. 相对于jwt来说,用来传输用户信息的网络流量更少
    3. 相对于jwt来说,适合做会话管理,单点登录。
  • jwt:
    • 缺点:
    1. jwt太长:由于是无状态使用JWT,所有的数据都被放到JWT里,如果还要进行一些数据交换,那载荷会更大,经过编码之后导致jwt非常长,cookie的限制大小一般是4k,cookie很可能放不下,所以jwt一般放在local storage里面。并且用户在系统中的每一次http请求都会把jwt携带在Header里面,http请求的Header可能比Body还要大。而sessionId只是很短的一个字符串,因此使用jwt的http请求比使用session的开销大得多。

    2. 由于jwt的payload是使用base64编码的,并没有加密,因此jwt中不能存储敏感数据。而session的信息是存在服务端的,相对来说更安全。

    3. 一次性:服务器签发的token,只能维持指定的一段时间,任何对数据的修改都会造成token失效。所以对于会话管理,这会带来极大的问题,比如用户一直处于活跃状态,但是token时间到了,用户也得被迫重新登录。而使用session,就可以随时修改更新其过期时间。

      为了解决这个问题,我们可以在redis中单独为每个jwt设置过期时间,每次访问时刷新jwt的过期时间,而不是在jwt中设置过期时间。

    4. 可控性:这实际上也是针对其一次性的问题而衍生出来的,可控性即服务端无法对用户做到很好的控制。比如,用户异地登录,你肯定想着换密码呀。换了以后发现我去,怎么又被异地登录。因为Token未过期,人家还是可以使用。这就很麻烦了。服务端根本不能控制。

      为了解决这个问题,我们就需要在服务端部署额外的逻辑,例如设置一个黑名单,一旦签发了新的jwt,那么旧的就加入黑名单(比如存到redis里面),避免被再次使用。

      可以看出想要破解jwt一次性和可控性差的缺点,就需要在服务端存储jwt的状态。但是引入 redis 之后,就把无状态的jwt硬生生变成了有状态了,违背了jwt的初衷。而且这个方案和session都差不多了。那还不如直接用session。

3.总结

适合使用jwt的场景:

有效期短
只希望被使用一次
比如,验证码,用户注册后发一封邮件让其激活账户,通常邮件中需要有一个链接,这个链接需要具备以下的特性:能够标识用户,该链接具有时效性(通常只允许几小时之内激活),不能被篡改以激活其他可能的账户,一次性的。这种场景就适合使用jwt。

而由于jwt具有一次性的特性。单点登录和会话管理非常不适合用jwt,如果在服务端部署额外的逻辑存储jwt的状态,那还不如使用session。基于session有很多成熟的框架可以开箱即用,但是用jwt还要自己实现逻辑。

发布了69 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/JustKian/article/details/94002865