首页 > 手机 > 配件 > Session,session

Session,session

来源:整理 时间:2022-04-07 16:41:30 编辑:华为40 手机版

搞不懂Session、Cookie、Token有何关系和区别?

搞不懂Session、Cookie、Token有何关系和区别

前段时间,刚好大致的了解过这三者的区别。为了方便理解,我们可以从传统的Session到Token的身份验证演变过程,来理解Session、Cookie、Token之间的关系。很久很久以前,Web应用基本用于文档的浏览,例如,网络黄页。既然是浏览,服务器也就不需要去记录具体用户在哪段时间里浏览了哪些文档,每一次请求都是一个新的HTTP协议,对服务器来说都是全新的,这时候没有Session、Cookie、Token。

基于Session的身份验证随着交互式Web应用的发展,比如,像购物等需要用户登录的网站。引出了一个问题,那就是网站需要记录哪些用户登录了系统进行了哪些操作,即要进行管理会话(什么是会话?简单的讲如果用户需要登录,那么就可以简单的理解为会话,如果不需要登录,那么就是简单的连接。),比如,不同用户将不同商品加入到自己的购物车中, 也就是说必须将每个用户区分开。

但因为HTTP请求是无状态的,所以想出了一个解决办法,那就是给每个用户发一个会话标识(Session id),简单的说就是给每个用户发一个既不重复,又不容易被找到规律进行仿造的随机字符串,以使每个用户收到的会话标识都不一样。 这样每次用户从客户端向服务端发起HTTP请求的时候,把这个字符串给一起发送过来, 服务端就可以区分开谁是谁了。

那么客户端(浏览器)如何保存这个“身份标识”的呢?,一般默认采用 Cookie(存储在浏览器目录中的文本文件) 的方式,这个会话标识(Session id)会存在客户端的Cookie中。虽然上面的方法解决了区分用户的问题,但同时也引入了一个新的问题,那就是每个用户(客户端)只需要保存自己的会话标识(Session id),而服务端则要保存所有用户的会话标识(Session id)。

当访问服务端的用户逐渐变多,服务端那就需要存储成千上万,甚至几千万个,这对服务器说是一个难以接受的开销 。我们再举一个简单的例子,假如服务端是由2台服务器组成的一个集群, 小明通过服务器A登录了系统, 那 Session id会保存在服务器A上, 假设小明的下一次请求被转发到服务器B怎么办? 服务器B可没有小明 的 Session id。

可能会有人讲,如果使小明登录时,始终在服务器A上进行登录(sticky session),岂不解决了这个问题?那如果服务器A挂掉怎么办呢? 还是会将小明的请求转发到服务器B上,问题仍然存在。如此一来,那只能做集群间的 Session 复制共享了, 就是把 Session id 在两个机器之间进行复制,如下图,但这又对服务器的性能和内存提出了巨大的挑战。

因此,又想到如果将所有用户的Session集中存储呢,也就想到了缓存服务Memcached——由于 Memcached 是分布式的内存对象缓存系统,因此可以用来实现 Session 同步。把Session id 集中存储到一台服务器上, 所有的服务器都来访问这个地方的数据, 如此就避免了复制的方式, 但是这种“集万千宠爱于一身”使得又出现了单点故障的可能, 就是说这个负责存储 Session 的服务器挂了, 所有用户都得重新登录一遍, 这是用户难以接受的。

那么索性将存储Session的服务器也设计为集群,增加可靠性,避免单点故障,但无论如何,Session 引发出来的问题似乎层出不穷。于是有人开始思考, 为什么服务端必须要保存 Session呢, 只让每个客户端去保存不行吗?可是服务端如果不保存这些Session id ,又将如何验证客户端发送的 Session id 的确是服务端生成的呢? 如果不验证,服务端无法判断是否是合法登录的用户,对,这里的问题是验证, session 只是解决这个验证问题的而产生的一个解决方案,是否还有其它方案呢?——于是,引出了基于Token 的身份验证。

基于Token 的身份验证例如, 张三已经登录了系统,服务端给他发一个令牌(Token), 里边包含了张三的 user id, 后续张三再次通过 Http 请求访问服务器的时候, 把这个 Token 通过 Http header 带过来不就可以了。服务端只需要验证 Token是自己生成的,而非伪造的。

假如不验证任何人都可以伪造,那么这个令牌(token)和 session id没有本质区别,如何让别人伪造不了?那就对数据做一个签名(Sign)吧, 比如说服务端用 HMAC-SHA256 加密算法,再加上一个只有服务端才知道的密钥, 对数据做一个签名, 把这个签名和数据一起作为 Token 发给客户端, 客户端收到 Token 以后可以把它存储起来,比如存储在 Cookie(存储在浏览器目录中的文本文件)中,由于密钥除了服务端任何其他用户都不知道, 就无法伪造令牌(Token)。

这样一来,服务端就可以不保存 Token 了, 当张三把这个Token发给服务端时,服务端使用相同的HMAC-SHA256 算法和密钥,对数据再计算一次签名, 与 Token 中的签名做个比较, 如果两者相同,说明张三已经登录过了, 即验证成功。若不相同, 那么说明这个请求是伪造的。这样一来, 服务端只需要生成 Token,而不需要保存Token, 只是验证Token就好了 ,也就实现了时间换取空间(CPU计算时间换取Session 存储空间)。

文章TAG:Sessionsession

最近更新