1.概述
我们都知道 HTTP 协议是无状态的,所谓的无状态就是客户端每次想要与服务端通信,都必须重新与服务端链接,意味着请求一次客户端和服务端就连接一次,下一次请求与上一次请求是没有关系的。
这种无状态的方式就会存在一个问题:如何判断两次请求的是同一个人?就好比用户在页面 A 发起请求获取个人信息,然后在另一个页面同样发起请求获取个人信息,我们如何确定这俩个请求是同一个人发的呢?
为了解决这种问题,我们就迫切需要一种方式知道发起请求的客户端是谁?此时,cookie、token、session 就出现了,它们就可以解决客户端标识的问题,在扩大一点就是解决权限问题。
它们就好比让每个客户端或者说登录用户有了自己的身份证,我们可以通过这个身份证确定发请求的是谁!
2. cookie
2.1 概念
Cookie 是一种在客户端存储数据的技术,它是由服务器发送给客户端的小型文本文件,存储在客户端的浏览器中,大小限制大致在 4KB 左右。在客户端发送请求时,浏览器会自动将相应的 Cookie 信息发送给服务器,服务器通过读取 Cookie 信息,就可以判断该请求来自哪个客户端。Cookie 可以用于存储用户的登录状态、购物车信息等。
在以前很多开发人员通常用 cookie 来存储各种数据,后来随着更多浏览器存储方案的出现,cookie 存储数据这种方式逐渐被取代,主要原因有如下:
1、cookie 有存储大小限制,4KB 左右。
2、浏览器每次请求会携带 cookie 在请求头中。
3、Cookie 本质存储的是字符串,若存储复杂或非 ASCII 数据,通常需要进行编码(如 URL Encode)。
4、数据可以被轻易查看。
2.2 cookie的主要属性
| 属性名 | 描述 |
|---|---|
| name | cookie 的名称 |
| value | cookie的值 |
| commit | cookie的描述信息 |
| domain | 可以访问该cookie的域名 |
| expires | cookie的过期时间,具体某一时间 |
| maxAge | cookie的过期时间 |
| path | cookie的使用路径 |
| secure | cookie是否使用安全协议传输,比如SSL等 |
| version | cookie使用的版本号 |
| isHttpOnly | 指定该 Cookie 无法通过 JavaScript 脚本拿到,比如 Document.cookie 属性、XMLHttpRequest 对象和 Request API 都拿不到该属性。这样就防止了该 Cookie 被脚本读到,只有浏览器发出 HTTP 请求时,才会带上该 Cookie。 |
2.3 cookie工作流程
- 客户端发送请求到服务端(比如登录请求)。
- 服务端收到请求后生成一个 session 会话。
- 服务端响应客户端,并在响应头中设置 Set-Cookie。Set-Cookie 里面包含了 sessionId,它的格式如下:Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]。其中 sessionId 就是用来标识客户端的,类似于去饭店里面,服务员给你一个号牌,后续上菜通过这个号牌来判断上菜到哪里。
- 客户端收到该请求后,如果服务器给了 Set-Cookie,那么下次浏览器就会在请求头中自动携带 cookie。
- 客户端发送其它请求,自动携带了 cookie,cookie 中携带有用户信息等。
- 服务端接收到请求,验证 cookie 信息,比如通过 sessionId 来判断是否存在会话,存在则正常响应。

2.4 cookie 主要特点
- cookie 存储在客户端
- cookie 不可跨域,但是在如果设置了 domain,那么它们是可以在一级域名和二级域名之间共享的。
3. session
3.1 概念
session 由服务端创建,当一个请求发送到服务端时,服务器会检索该请求里面有没有包含 sessionId 标识,如果包含了 sessionId,则代表服务端已经和客户端创建过 session,然后就通过这个 sessionId 去查找真正的 session,如果没找到,则为客户端创建一个新的 session,并生成一个新的 sessionId 与 session 对应,然后在响应的时候将 sessionId 给客户端,通常是存储在 cookie 中。如果在请求中找到了真正的 session,验证通过,正常处理该请求。
每一个客户端与服务端连接,服务端都会为该客户端创建一个 session,并将 session 的唯一标识 sessionId 通过设置 Set-Cookie 头的方式响应给客户端,客户端将 sessionId 存到 cookie 中。
3.2 流程图
通常情况下,cookie 和 session 都是结合着来用,当然你也可以单独只使用 cookie 或者单独只使用 session,这里我们就将 cookie 和 session 结合着来用。如下图,具体流程介绍看上面cookie流程即可。

3.2 session与cookie的区别
-
cookie 和 session,它们两者之间主要是通过 sessionId 关联起来的,所以总结出:sessionId 是 cookie 和 session 之间的桥梁。
-
session 是基于 cookie 实现的,它们两个主要有以下特点:
-
session 比 cookie 更加安全,因为它是存在服务端的,cookie 是存在客户端的。
-
cookie 只支持存储字符串数据,session 可以存储任意数据。
-
cookie 的有效期可以设置较长时间,session 有效期都比较短。
-
session 存储空间很大,cookie 有限制。
系统想要实现鉴权,可以单独使用 cookie,也可以单独使用 session,但是建议结合两者使用。
4. token
4.1 概念
Token 是一种在客户端和服务端之间传递身份信息的方式。当用户登录成功后,服务端会生成一个 Token,将其发送给客户端。客户端在后续的请求中,需要将 Token 携带在请求头或请求参数中。服务端通过验证 Token 的合法性,就可以确定该请求来自哪个用户,并且可以根据用户的权限进行相应的操作。Token 可以有效地避免了 Cookie 的一些安全问题,比如 CSRF 攻击。
4.2 token的组成
Token是一个由一串字符组成的令牌,用于在计算机系统中进行身份验证和授权。它通常由三个部分组成:标头、有效载荷、签名。
标头(Header):包含了算法和类型,用于指定如何对有效载荷进行编码和签名。常用的算法有HMAC、RSA、SHA等。
有效载荷(Payload):包含了一些信息,如用户ID、角色、权限等,用于验证身份和授权。有效载荷可以是加密的,也可以是明文的。
签名(Signature):是对标头和有效载荷进行签名后得到的值,用于验证token的完整性和真实性。签名通常使用私钥进行签名,并使用公钥进行验证。
一个完整的token包含了标头、有效载荷和签名三个部分,它们一起构成了一个安全的令牌,用于进行身份验证和授权。
4.3 token认证流程
- 客户端发起登录请求,比如用户输入用户名和密码后登录。
- 服务端校验用户名和密码后,将用户 id 和一些其它信息进行加密,生成 token。
- 服务端将 token 响应给客户端。
- 客户端收到响应后将 token 存储下来。
- 下一次发送请求后需要将 token 携带上,比如放在请求头中或者其它地方。
- 服务端 token 后校验,校验通过则正常返回数据。

5. Cookie、session、token的区别
| 特点 | 优点 | 缺点 | |
|---|---|---|---|
| cookie | 1.存储在客户端。 2.请求自动携带 cookie。 3.存储大小 4KB。 | 1.兼容性好,因为是比较老的技术。 2.很容易实现,因为 cookie 会自动携带和存储。 | 1.需要单独解决跨域携带问题,比如多台服务器如何共享 cookie。 2.会遭受 CSRF 攻击。 3.存储在客户端,不够安全。 |
| session | 1.存储在服务端。 2.存储大小无限制。 | 1.查询速度快,因为是个会话,相当于是在内存中操作。 2.结合 cookie 后很容易实现鉴权。 3.安全,因为存储在服务端。 | 1.耗费服务器资源,因为每个客户端都会创建 session。 2.占据存储空间,session 相当于存储了一个完整的用户信息。 |
| Token | 1.体积很小。 2.自由操作存储在哪里。 | 1.安全,因为 token 一般只有用户 id,就算被截取了也没什么用。 2.无需消耗服务器内存资源,它相当于只存了用户 id,session 相当于存储了用户的所有信息。 3.跨域处理较为方便,比如多台服务器之间可以共用一个 token。 | 1.查询速度慢,因为 token 只存了用户 id,每次需要去查询数据库。 |
注:使用token现在有了redis缓存中间件,不必频查数据库,查询一次后缓存使用
6.补充
问:cookie和session是不是都是由服务端产生呢?
Cookie 分两种(只有「服务器端 Cookie」由服务器产生,客户端 Cookie 可由浏览器前端生成);Session 确实是由服务器产生并存储的。
6.1 Cookie:分「服务器端生成」和「客户端生成」
Cookie 是存储在浏览器客户端的小型文本文件(键值对格式),它的产生来源有两个:
1. 服务器端生成
这是最常见的场景,流程如下:
- 客户端(浏览器)发送第一次请求(比如登录请求)到服务器;
- 服务器验证通过后,在响应头中添加
Set-Cookie字段,携带 Cookie 信息(如会话标识、过期时间等); - 浏览器接收到响应后,自动将
Set-Cookie中的内容保存到本地(客户端); - 后续客户端向该服务器发送请求时,会自动在请求头中携带对应的 Cookie,供服务器识别身份。
示例(HTTP 响应头中的 Set-Cookie):
Set-Cookie: sessionid=123456abcdef; Path=/; Domain=xianjianai.com; Max-Age=3600
这种 Cookie 就是由服务器产生的,主要用于「身份识别、会话维持」(比如登录后保持登录状态),也是你在 Selenium/requests 中操作的核心 Cookie 类型。
2. 客户端生成(前端 JS 操作)
浏览器允许前端通过 JavaScript 直接创建 Cookie(存储在客户端),这种 Cookie 完全与服务器无关,仅在客户端生效。
示例(前端 JS 创建 Cookie):
javascript
// 前端控制台执行,创建一个客户端 Cookie(服务器不会感知)
document.cookie = "username=test_user; expires=Fri, 31 Dec 2026 23:59:59 GMT; path=/";
浏览器允许前端通过 JavaScript 使用 document.cookie 创建 Cookie。
这类 Cookie 存储在客户端,但只要其 Domain 和 Path 与请求匹配,仍会在 HTTP 请求中自动发送给服务器 。
与服务器下发的 Cookie 相比,前端创建的 Cookie 无法设置 HttpOnly 属性,安全性较低,因此通常仅用于前端可控的非敏感数据。
6.2 Session:完全由服务器产生并存储
Session 通常称为「会话」,它的核心特点是由服务器产生、存储在服务器端,流程如下:
- 客户端第一次发送请求到服务器,服务器会创建一个唯一的 Session(包含会话 ID、会话数据、过期时间等);
- 服务器将 Session 的「唯一标识(Session ID)」通过「服务器端 Cookie」返回给客户端(即上面第一种 Cookie);
- 客户端后续请求时,会携带这个包含 Session ID 的 Cookie 到服务器;
- 服务器通过 Session ID 找到对应的 Session 数据,从而识别客户端身份、获取会话信息。
关键补充:
- Session 数据存储在服务器端(可以是内存、数据库、Redis 等),客户端仅存储「Session ID」(通过 Cookie 传递);
- Session 不能由客户端创建,因为它是服务器端的会话记录,客户端无法干预服务器的存储数据;
- 若客户端禁用 Cookie,服务器会通过「URL 重写」(将 Session ID 拼接在 URL 后)传递 Session ID,但这种方式安全性较低,现在很少使用。
6.3 核心区别总结(Cookie vs Session)
| 特性 | Cookie | Session |
|---|---|---|
| 产生来源 | 服务器(核心)、客户端(前端JS) | 仅服务器产生 |
| 存储位置 | 客户端(浏览器本地) | 服务器端(内存/数据库/Redis等) |
| 存储大小限制 | 有(单个 Cookie 通常 ≤ 4KB) | 无(由服务器存储能力决定) |
| 安全性 | 较低(存储在客户端,易被篡改) | 较高(存储在服务器,仅暴露 Session ID) |
总结
- Cookie 是浏览器的存储与传输机制,可以由服务器或客户端生成,只要域匹配就会随请求发送;
- Session 是服务器端的会话数据结构,只能由服务器创建和维护,客户端仅通过 Cookie 等方式携带 SessionID;
- HTTP 协议并不区分 Cookie 的创建来源,服务器只能看到浏览器最终发送的 Cookie 键值对。