Cookie、Session、Token的区别
什么是 Cookie
Cookie 技术的产生源于 HTTP 协议在互联网上的急速发展。由于 HTTP 是无状态的会话,在互联网飞速发展的今天,人们进行更复杂的互联网交互活动,就必须同服务器保持活动状态,Cookie 技术便是一种保持 Web 浏览状态的手段。
Cookie 是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现 Session 的一种方式。Cookie 存储的数据量有限,且都是保存在客户端浏览器中。不同的浏览器有不同的存储大小,但一般不超过 4KB。因此使用 Cookie 实际上只能存储一小段的文本信息(key-value 格式)。
Cookie 的机制
当用户第一次访问并登录一个网站的时候,Cookie 的设置以及发送会经历以下4个步骤:
- 客户端发送一个请求到服务器;
- 服务器发送一个 HttpResponse 响应到客户端,其中包含 Set-Cookie 的头部;
- 客户端保存 cookie,之后向服务器发送请求时,HttpRequest 请求中会包含一个 Cookie 的头部;
- 服务器返回响应数据。
什么是 Session
由于 Cookie 是存在于客户端的,将用户详细信息通过网络发送到客户端保存是极不安全的。且 Cookie 大小不能超过4k,不能支持中文。这就限制 Cookie 不能满足存储用户信息的需求。这就需要一种机制在服务器端的某个域中存储一些数据,这个域就是 Session。
在 Web 开发中,服务器可以为每个用户浏览器创建一个会话对象(Session 对象),注意:一个浏览器独占一个 Session 对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的 Session 中,当用户使用浏览器访问其它程序时,其它程序可以从用户的 Session 中取出该用户的数据,为用户服务。
Session 的机制
Session 是服务端存储的一个对象,主要用来存储所有访问过该服务端的客户端的用户信息(也可以存储其他信息),从而实现保持用户会话状态。Session ID 放入 Cookie 由客户端保存,减少服务端的负担。
-
服务器在处理客户端请求过程中会创建 Session,并且为该 Session 生成唯一的 Session ID。(这个 Session ID 在随后的请求中会被用来重新获得已经创建的 Session。在 Session 被创建后,就可以调用 Session 相关的方法向 Session 中新增内容,这些内容只会保存在服务器中)。
-
服务器将 Session ID 发送到客户端。
-
当客户端再次请求时,就会带上这个 Session ID。
-
服务器接收到请求之后就会依据 Session ID 找到相应的 Session,完成请求。
Cookie 和 Session 的区别
-
Cookie 数据存放在客户的浏览器上, Session 数据放在服务器上。
-
Cookie 不是很安全,别人可以分析存放在本地的 Cookie 并进行 Cookie 欺骗,考虑到安全应当使用 Session。
-
Session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用 Cookie。
-
单个 Cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 Cookie。
什么是 Token
Token 的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。
当用户第一次登录后,服务器生成一个 Token 并将此 Token 返回给客户端,以后客户端只需带上这个 Token 前来请求数据即可,无需再次带上用户名和密码,减轻服务器压力,避免频繁查询数据库。
简单 Token 的组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名, Token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止 Token 泄露)。
Token 与 Session 对比
Token 和 Session 并不矛盾,都是用户身份认证的一种识别手段,作为身份认证 Token 安全性比 Session 好,因为每个请求都有签名还能防止监听以及重放攻击,而 Session 就必须靠链路层来保障通讯安全了。
传统的应用是将 Session 放在应用服务器上,而将生成的 Session ID 放在用户浏览器的 Cookie 中,而这种模式在前后端分离中就会出现以下问题:
- 开发繁琐。
- 安全性和客户体验差
- 有些前端技术不支持 Cookie,如微信小程序
这种情况下,前后端之间使用 Token(令牌)进行通信就完美的解决上面的问题。
Token 优缺点
优点
-
支持跨域访问: Cookie 是不允许跨域访问的, Token 支持;
-
无状态: Token 无状态, Session 有状态;
-
去耦: 不需要绑定到一个特定的身份验证方案。Token 可以在任何地方生成,只要在你的 API 被调用的时候,你可以进行 Token 生成调用即可;
-
更适用于移动应用: Cookie不支持手机端访问的;
-
性能: 在网络传输的过程中,性能更好;
-
基于标准化: 你的 API 可以采用标准化的 JSON Web Token (JWT)。这个标准已经存在多个后端库(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft)。
缺点
-
占带宽,正常情况下要比 Session_id 更大,需要消耗更多流量,挤占更多带宽,假如你的网站每月有 10 万次的浏览器,就意味着要多开销几十兆的流量。听起来并不多,但日积月累也是不小一笔开销。实际上,许多人会在 JWT 中存储的信息会更多;
-
无法在服务端注销,那么久很难解决劫持问题;
-
性能问题,JWT 的卖点之一就是加密签名,由于这个特性,接收方得以验证 JWT 是否有效且被信任。但是大多数 Web 身份认证应用中,JWT 都会被存储到 Cookie 中,这就是说你有了两个层面的签名。听着似乎很牛逼,但是没有任何优势,为此,你需要花费两倍的 CPU 开销来验证签名。对于有着严格性能要求的 Web 应用,这并不理想,尤其对于单线程环境。