会话(Session)跟踪是 Web 程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是 Cookie 与 Session。Cookie通 过在客户端记录信息确定用户身份,Session 通过在服务器端记录信息确定用户身份。
本篇内容包括:会话 Session 发展史(包括会话 Session 的产生、会话 Session 的问题 和 会话 Session 的问题解决),Cookie(Cookie 的概念、Cookie 的类型),Session(实现)(Session 的概念、Cookie 的类型)以及 其他相关知识点的内容!
文章目录
一、会话 Session 发展史
1、会话 Session 的产生
在开始的阶段,Web 的使用场景往往仅限于网页浏览,即 每次请求都是一个新的 HTTP 协议,也不需要记录谁在某一段时间里都浏览了什么文档。
在后面的阶段,随着类似于购物网站的交互式 Web 页面/应用的兴起,开始出现了需要用户登录的需要,即服务器需要记录登陆了哪些人,哪些人购买了哪些商品,也就是对客户端需要进行区分。
- 应对此种变化的方式就是:服务器端会给请求的客户端下发一个 SessionId,即 会话标识,齐通常由一串唯一字符构成,客户端携带着 SessionId,就可以被 服务端区分了。
2、会话 Session 的问题
接下来的阶段,随着交互式 Web 网站用户的增加,服务端开始发现一个问题,即「每个客户端只需保存自己的 SessionId,而服务端需要保存所有 SessionId,随着访问服务的增加,记录 SessionId 的开销饿越来越大,严重的限制了服务器扩展能力」
- 场景一:两个机器组成了一个集群保存 SessionId 信息,用户通过机器 A 登录了系统, 那 SessionId 会保存在机器 A 上,则当请求机器 B 时会找不到 SessionId;
- 场景二:将用户请求一直粘在机器 A 上,但假如机器 A 挂掉,依然会走到机器 B
- 场景三:做 Session 复制,SessionId 在两台机器来回复制…?
- 场景四:把 SessionId 集中存储到一个地方,所有的机器都来访问这个地方的数据,这样一来,就不用复制了,但是增加了单点失败的可能性!
3、会话 Session 的问题解决
再后来的阶段,开始有人思考, 为什么要保存 Session 信息在服务端呢,在客户端保存是否会有更好的效果?
可是如果不保存这些 SessionId,怎么验证客户端发给我的 SessionId 的确是我生成的呢?关键点就是验证 !
比如说,用户小 A 已经登录了系统, 我给他发一个令牌(Token), 里边包含了小 A 的 userId,下一次小 A 再次通过 Http 请求访问服务端的时候, 把这个 Token 通过 Http header 带过来就可以了。但为了避免被伪造,可以做个签名,比如说用 HMAC-SHA256 算法,加上一个只有服务端才知道的密钥,对数据做一个签名,把这个签名和数据一起作为Token,由于密钥别人不知道, 就无法伪造 Token 了。
这个 Token 服务端不保存, 当小 A 把这个 Token 给服务端发过来的时候,服务端再用同样的 HMAC-SHA256 算法和同样的密钥,对数据再计算一次签名,和 Token 中的签名做个比较, 如果相同, 我就知道小 A 已经登录过了,并且可以直接取到小 A 的 userId , 如果不相同, 数据部分肯定被人篡改过, 我就告诉发送者:“对不起,没有认证“。
这样一来,服务端就不保存 SessionId 了,服务端只是生成 Token ,然后验证 Token,服务端用服务端的 CPU 计算时间获取了服务端的 Session 存储空间 !
Ps:当然如果一个人的 Token 被别人偷走了, 那谁也没办法
二、Cookie
1、Cookie 的概念
Cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。其本质是某些网站为了辨别用户身份,进行 Session 跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息
Cookie 由服务器生成,发送给浏览器,浏览器把 Cookie 以 kv 形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该 Cookie 发送给服务器。由于 Cookie 是存在客户端上的,所以浏览器加入了一些限制确保 Cookie 不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的 Cookie 数量是有限的。
2、Cookie 的类型
Cookie 总时由用户客户端进行保存的(一般是浏览器),按其存储位置可分为:内存式 Cookie 和硬盘式 Cookie。
内存式 Cookie 存储在内存中,浏览器关闭后就会消失,由于其存储时间较短,因此也被称为非持久 Cookie 或会话 Cookie。
硬盘式 Cookie 保存在硬盘中,其不会随浏览器的关闭而消失,除非用户手工清理或到了过期时间。由于硬盘式 Cookie 存储时间是长期的,因此也被称为持久 Cookie。
三、Session(实现)
Ps:不要混淆 Session 和 Session 实现。
1、Session 的概念
Session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是 Session。客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就可以了。
服务器使用 Session 把用户的信息临时保存在了服务器上,用户离开网站后 Session 会被销毁。这种用户信息存储方式相对 Cookie 来说更安全,可是 Session 有一个缺陷:如果 web 服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候 Session 会丢失。
2、Session 的原理
当程序需要为某个客户端的请求创建一个 Session 的时候,服务器首先检查这个客户端的请求里是否已包含了一个 Session 标识,称为 SessionId,
- 如果客户端已包含一个 SessionId 则说明以前已经为此客户端创建过Session,服务器就按照 SessionId 把这个Session检索出来使用(如果检索不到,可能会新建一个);
- 如果客户端请求不包含 SessionId ,则为此客户端创建一个Session并且生成一个与此Session相关联的 SessionId , SessionId 的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 SessionId 将被在本次响应中返回给客户端保存。
四、相关知识点
1、Cookie 与 Session 的区别与联系
两者的区别:
1、Cookie 数据存放在客户端,Session 数据放在服务器上。
2、Cookie 不是很安全,别人可以分析存放在本地的 Cookie 并进行 Cookie 欺骗,考虑到安全应当使用 Session。
3、Session 会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑性能应当使用 Cookie。
4、不同浏览器对 Cookie 的数据大小限制不同,个数限制也不相同。单个 Cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 Cookie。
5、可以考虑将登陆信息等重要信息存放为 Session,不重要的信息可以放在 Cookie 中。
两者的联系:
1、都是用来记录用户的信息,以便让服务器分辨不同的用户。
2、可以搭配使用,但都有自己的使用局限,要考虑到安全和性能的问题。
2、关于 Token
Token,即访问资源接口(API)时所需要的资源凭证
简单 Token 的组成: uid(用户唯一的身份标识) 、time (当前时间的时间戳) ,sign(签名,Token 的前几位以 hash 算法压缩成的一定长度的 16 进制字符串)
特点:服务端无状态变化、可扩展性好,支持移动端设备,安全,支持跨域程序调用,Token 的身份验证流程
基于 Token 的验证原理(过程)
- 客户端使用用户名和密码进行登录
- 服务端收到请求,去验证用户名与密码
- 验证成功后,服务端会签发一个 Token 并把这个 Token 发送给客户端
- 客户端收到 Token 后,会把它存储起来,比如放在 Cookie 里 或者 localStorage 里
- 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
- 服务端收到请求后,先验证客户端请求里带着的 Token ,如果验证成功,就向客户端返回请求的数据