一文搞懂session、cookie、token的关系和渊源

对于web应用,因为http请求是无状态的,无状态可以理解为随用随消亡,即客户端和服务端在一次通信完成后连接便会自动断开,下次通信需要重新建
连。对于一个多业务相关联的应用程序来讲,这显然是不合适的,比如一个购物网站,可能会发生这样的情况:用户每浏览一个商品都需要重新登录一下,
否则可能会发生张三为李四的商品买了单并送到了王五手里。那么如何保证是同一个用户并维持会话呢,为了解决这一问题,session和cookie诞生了。

那么session和cookie是怎样生成和作用的呢,如下:
第一步,客户端携带用户名和密码发送登录请求,服务端收到请求首先对比数据库校验用户名和密码的合法性,校验通过后生成一个session并将sessi
onid返回给客户端,同时将session存储起来(可以存储在服务器内存或者redis)。
第二步,客户端收到服务端发来的sessionid后,将其放在cookie中,并将cookie存储在浏览器缓存或者本地磁盘中,在之后发起的需要认证的请求
时携带cookie,服务端通过cookie中的sessionid校验session的有效性,并做出响应返回给客户端。

那么服务端是怎样校验session的有效性的呢,如下:
有效性包括正确性和时效性,正确性很好理解,cookie中的sessionid可以在服务端找到。对于时效性,每一个session在生成的时候都会自带一个有
效时长(java程序在tomcat中设置,默认是30分钟),在有效时长内,针对同一个用户,服务端每收到一次请求,session的有效时长更新一次,当超
过有效时长没有再收到客户端请求,服务端结束会话,并清除此session。

总结:session主要用于鉴权和保持会话。

那么token是做什么用的呢,如下:
token的作用依然是鉴权和保持会话。既然和session作用一样,继续用session不就好了吗?随着互联网的发展,应用程序日渐复杂和多样化,比如为
了实现高并发高可靠诞生了分布式集群技术,分布式集群需要不同服务器之间session共享,有一种办法是将session复制到不同的服务器内存中,这显
然会消耗大量内存空间,造成内存浪费(有人说存到redis也可以实现session共享且不会占用服务器内存空间,然而redis也是服务端的一部分,且会
增加数据操作开销),比如前后端分离(各自使用不同的服务器,分别为web服务器和应用服务器,通过API接口交互),比如移动端app没有cookie。
于是有人想出了不用session的办法,并给他取名为token。

那么token是怎样生成及实现鉴权、保持会话的呢,如下:
第一步,客户端携带用户名和密码发送登录请求,服务端收到请求首先对比数据库校验用户名和密码的合法性,校验通过后通过JWT(json web token)
生成一个包含加密算法(HS256)、用户信息、有效时长和签名并且经过加密的access token,然后将access token返回给客户端(服务端不保存tok
en,通过加密和验签实现鉴权)。
第二步:客户端收到服务端发来的access token,保存在cookie或者本地磁盘中,在之后发起需要鉴权的请求时,在URL参数或HTTP Header中加入
token,服务端通过解密和验签校验token的有效性(正确性和时效性),并做出响应返回给客户端。
这种方式虽然简化了服务端架构(缓存)、减轻了服务器的压力(session)、减少了频繁的查询数据库(用户信息),但是也有一个缺点:会话只能
通过客户端清除,否则在有效时长内,会话会一直保持,无法实现禁用用户的功能。于是出现了一种折中方案:refresh token。

那么什么是refresh token呢,如下:
refresh token是和access token一起由服务端生成的,区别是refresh token的有效期大于access token,并且refresh token需要存储
在服务端。当access token过期而refresh token未过期时,客户端携带refresh token向服务端请求生成新的access token,客户端拿到新
的access token继续完成请求。

总结:使用session还是token要视情况而定,选择折中方案。

如有不对,欢迎指正。


 




posted @ 2022-09-09 14:27  菜花小兔  阅读(116)  评论(3编辑  收藏  举报