一文彻底搞清session、cookie、token的区别

1 概述:无状态的困境与身份认证的诞生

HTTP 协议的核心特征之一是无状态。这意味着服务器不会“记住”它处理过的每一个请求。每一次客户端(如浏览器)向服务器发起请求,都被视为一次全新的、独立的对话。服务器处理完请求后,连接就关闭,不会保留任何关于这次请求或之前请求的上下文信息。

这种设计简单高效,但也带来了一个核心问题:如何关联多次请求? 例如,用户登录成功后,在后续访问个人主页或购物车页面时,服务器如何确认这些请求都是同一个合法用户发出的?服务器需要一种方法来识别“谁”在请求。

为了解决这个身份认证与状态保持的难题,Cookie、Session 和 Token 应运而生。它们本质上都是为客户端(或代表用户的请求)提供一种身份凭证。这就像给每个登录用户或设备颁发了一张“身份证”,服务器通过验证这张“身份证”,就能识别请求来源,进而实现访问控制(权限管理)和个性化服务。

2 深入剖析:Cookie

2.1 概念与定位
Cookie 是由服务器生成并发送给客户端(通常是浏览器)保存的一小块文本数据。当客户端再次向同一服务器发起请求时,浏览器会自动将与该服务器关联的 Cookie 附加在请求头中发送回去。服务器通过解析这些 Cookie,就能获取之前存储的状态信息(如用户标识、偏好设置等),从而实现状态的保持。

Cookie 主要存储在客户端浏览器端,有大小限制(通常约 4KB)。虽然早期曾被广泛用于存储各种客户端数据,但随着 Web Storage (LocalStorage, SessionStorage) 等更优方案的普及,Cookie 在现代 Web 开发中主要专注于其核心职责:在客户端可靠地存储和传递身份标识或会话信息,以支持身份认证和状态管理。

2.2 主要属性详解

Cookie 的配置依赖于其属性,这些属性共同决定了 Cookie 的行为:

属性名描述
nameCookie 的唯一标识名称。
valueCookie 存储的实际值(字符串形式)。
domain指定 Cookie 有效的域名范围。例如,设置为 .example.com,则 a.example.com 和 b.example.com 都可访问该 Cookie。
path指定 Cookie 在域名下的有效路径。只有请求路径匹配该路径或其子路径时,才会携带该 Cookie。默认为 /
expires指定一个具体的 GMT/UTC 时间作为 Cookie 的过期时间。过期后浏览器将自动删除该 Cookie。
maxAge指定 Cookie 从现在起存活的秒数。优先级高于 expires。设置为 0 表示立即删除,为负数表示会话结束(关闭浏览器)时删除。
secure布尔值。若为 true,则 Cookie 在通过 HTTPS 等安全加密连接时才会被发送。
httpOnly布尔值。若为 true,则该 Cookie 无法通过客户端的 JavaScript 脚本(如 document.cookie)读取或修改。这能有效降低 XSS(跨站脚本攻击)窃取敏感 Cookie 的风险。
sameSite控制浏览器是否在跨站请求中发送 Cookie。可选值:Strict(严格禁止跨站发送)、Lax(宽松,允许部分安全跨站请求如导航链接)、None(允许跨站发送,但必须同时设置 Secure)。现代浏览器默认常为 Lax

2.3 核心工作流程(结合 SessionId)

Cookie 最常见的用途是存储 Session ID,实现基本的会话管理。其流程如下:

  1. 登录请求: 用户提交登录信息(如用户名密码)到服务器。

  2. 会话创建: 服务器验证凭据通过后,在服务器端创建一个新的会话(Session),其中存储了与该用户相关的状态信息(如用户ID、登录状态)。服务器为该会话生成一个全局唯一的标识符:Session ID

  3. 设置 Cookie: 服务器在响应头中添加 Set-Cookie 指令,将 Session ID 作为 Cookie 的值发送给客户端。例如:Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure

  4. 客户端存储: 浏览器接收到响应后,会按照指令将包含 Session ID 的 Cookie 安全地(如果设置了 HttpOnly 和 Secure)存储在本地。

  5. 后续请求: 当用户访问该网站的其他页面时,浏览器会自动在请求头中携带与该域名和路径匹配的 Cookie(即包含 sessionId=abc123 的 Cookie)。

  6. 会话识别: 服务器收到请求后,从请求头的 Cookie 中提取 Session ID。然后根据这个 ID 去查找服务器端存储的对应 Session 对象。

  7. 请求处理: 如果找到有效的 Session,服务器就知道当前请求来自已登录的用户,并可以使用 Session 中存储的信息处理请求(如显示用户名)。如果 Session 无效或过期,服务器会要求用户重新登录。

2.4 关键特性总结

  • 客户端存储: 数据存储在浏览器端。

  • 自动携带: 满足域名、路径、安全条件时,浏览器自动在请求中附加 Cookie。

  • 大小限制: 约 4KB,且单个域名下 Cookie 数量也有限制。

  • 安全依赖: 敏感 Cookie(如 Session ID)应始终设置 Secure(仅 HTTPS)和 HttpOnly(防 XSS)属性。SameSite 属性是防御 CSRF(跨站请求伪造)攻击的重要手段。

  • 域限制: Cookie 默认不可跨域,但通过设置 domain 属性可在一级域名及其子域名间共享。

3 深入剖析:Session

3.1 概念与定位
Session 代表的是服务器端为特定用户(客户端)创建的一次交互会话上下文。当用户首次访问服务器或完成登录时,服务器会为其创建一个唯一的 Session 对象。这个对象存储在服务器的内存、文件系统、数据库或缓存(如 Redis)中。

Session 的核心作用是在服务器端安全地存储和管理用户的状态信息(如用户ID、登录状态、购物车内容、临时数据等)。与 Cookie 存储少量标识信息不同,Session 可以存储更丰富、更敏感的数据,且数据本身不直接暴露给客户端。

3.2 Session ID 的传递与关联
Session 本身存在于服务器端,客户端如何与它关联呢?答案就是 Session ID。服务器创建 Session 后,会生成一个唯一的 Session ID,并通过 Set-Cookie 指令(如 sessionId=abc123)发送给客户端浏览器存储(即上文 Cookie 流程中的第 2、3 步)。后续请求中,客户端浏览器通过 Cookie 将这个 Session ID 带回给服务器(第 5 步)。服务器收到请求后,解析出 Session ID(第 6 步),并用它来查找对应的服务器端 Session 对象(第 7 步)。因此,Session ID 是连接客户端 Cookie 与服务器端 Session 对象的桥梁

3.3 Session 工作流程图

3.4 与 Cookie 的核心区别与联系

  • 存储位置:

    • Cookie:数据存储在客户端(浏览器)。

    • Session:数据存储在服务器端

  • 安全性:

    • Session:更安全。敏感数据(如用户身份、权限)存储在服务器,客户端只持有无意义的 Session ID(仍需妥善保护该 ID)。

    • Cookie:存储在客户端,存在被窃取(XSS)或篡改的风险。敏感信息不应直接存储在 Cookie 中。

  • 存储内容与容量:

    • Cookie:只能存储字符串,容量小(~4KB),受浏览器限制。

    • Session:可存储任意类型数据(对象、数组等),容量理论上只受服务器资源限制。

  • 生命周期:

    • Cookie:可通过 expires/maxAge 设置较长的有效期(如记住我功能)。

    • Session:通常有效期较短(如用户不活动 30 分钟后过期),依赖于 Session ID 的传递(若 Cookie 失效或用户清除 Cookie,Session 即失效)。服务器端也可主动清理 Session。

  • 依赖关系:

    • Session 的识别通常依赖于 Cookie 来传递 Session ID。虽然也可以通过 URL 重写等方式传递,但 Cookie 是最主流、最方便的方式。

4 深入剖析:Token

4.1 概念与定位
Token(令牌)是一种自包含的、用于在客户端和服务端之间安全传递身份和授权信息的凭证。与 Session 不同,Token 的设计理念是无状态(Stateless):服务器不需要在本地存储会话信息。用户登录成功后,服务器生成一个 Token 并发送给客户端。客户端在后续请求中携带此 Token(通常在 Authorization 请求头中,如 Bearer <token>)。服务器只需验证 Token 本身的有效性(签名是否合法、是否过期等)和其中包含的信息(如用户ID、权限),即可完成身份认证和授权,无需去查询服务器端的会话存储。

Token 是解决分布式系统、跨域认证(如单点登录 SSO)、移动应用 API 认证等场景下状态管理问题的理想方案。常见的 Token 标准是 JWT (JSON Web Token)

4.2 Token 的核心组成(以 JWT 为例)
一个典型的 Token (JWT) 由三部分组成,用点 (.) 分隔:

  1. Header (标头): 通常包含 Token 的类型(如 JWT)和签名算法(如 HS256RS256)。例如:{"alg": "HS256", "typ": "JWT"}。此部分会进行 Base64Url 编码。

  2. Payload (有效载荷): 包含需要传递的声明(Claims)。声明是关于实体(通常是用户)和附加数据的语句。常见声明包括:

    • 注册声明 (Registered Claims): 预定义的标准字段(非强制),如 iss (签发者), exp (过期时间), sub (主题/用户ID), aud (受众) 等。

    • 公共声明 (Public Claims): 可自定义的、公开的字段。

    • 私有声明 (Private Claims): 自定义的、在通信双方之间共享的字段(如 userIdrole)。此部分也会进行 Base64Url 编码。注意:Payload 默认是可见的(Base64Url 可解码),因此不应在 Payload 中存储敏感信息(如密码)。如需存储敏感信息,必须对 Token 整体进行加密(JWE)。

  3. Signature (签名): 将编码后的 Header、编码后的 Payload 和一个密钥(Secret,只有服务器知道)通过 Header 中指定的签名算法(如 HMAC SHA256)计算生成。签名用于验证 Token 在传输过程中没有被篡改,并且证明该 Token 是由持有密钥的合法服务器签发的。

一个完整的 JWT 格式:xxxxx.yyyyy.zzzzz (Header.Payload.Signature)。

4.3 Token 认证流程

  1. 登录请求: 客户端发送登录凭证(用户名/密码等)到认证服务器。

  2. 验证凭证 & 生成 Token: 服务器验证凭证有效后,使用预定义的密钥和算法(如 HS256)生成一个 JWT。Payload 中通常包含用户标识(如 sub: user123)、过期时间(exp)和其他必要信息。

  3. 返回 Token: 服务器将生成的 Token 返回给客户端(通常在响应体中)。

  4. 客户端存储 Token: 客户端(浏览器、移动App)安全地存储此 Token(如 Web Storage、安全 Cookie、移动端安全存储)。

  5. 携带 Token 请求: 客户端访问受保护的 API 或资源时,在请求头(通常是 Authorization: Bearer <token>)或请求参数(较少推荐)中携带此 Token。

  6. 验证 Token: 资源服务器(或 API 网关)收到请求:

    • 检查 Authorization 头是否存在且格式正确。

    • 提取 Token。

    • 验证签名: 使用相同的密钥和算法对 Header + Payload 重新计算签名,并与 Token 中的 Signature 部分进行比对,确保 Token 未被篡改。

    • 验证声明: 检查 exp 确保 Token 未过期;检查 iss 确认签发者可信;检查 aud 确认 Token 是发给本服务的(可选)等。

  7. 处理请求: 如果 Token 验证通过,服务器解析 Payload(如获取 sub 中的用户ID),根据其中的信息进行授权(如检查用户是否有权限访问该资源)并处理请求。服务器在此过程中无需查询数据库或缓存中的会话状态(无状态)。如果验证失败,返回 401 Unauthorized 或 403 Forbidden 错误。

### CookieSessionToken区别 #### 定义与工作原理 Cookie 是一种小型文本文件,由服务器发送给浏览器并存储于用户的设备上。当用户再次访问同一网站时,浏览器会将这些 Cookies 发送回服务器[^1]。 Session 是一种用于跟踪用户状态的技术,在服务端创建唯一的标识符并与特定用户关联起来。每次HTTP请求都通过该唯一ID来识别属于哪个用户的交互过程[^2]。 Token 则是一种自包含的字符串形式的身份验证凭证,通常采用 JSON Web Tokens (JWT) 格式编码而成。它包含了关于用户的信息以及签名部分以确保其真实性。客户端可以在本地(如浏览器中的 `localStorage` 或者作为 HTTP 请求头的一部分)保存此令牌,并随后续请求一起提交给 API 接口进行权限校验[^3]。 #### 存储位置 Cookies 被存放在客户端机器上的浏览器环境中;Sessions 数据则主要位于服务器一侧;而Tokens既可以被放置在前端应用内部也可以嵌入到API调用里去。 #### 使用场景 对于传统的Web应用程序来说,如果前后端部署在同一台物理机或者同一个域名之下,则可以考虑使用 Sessions 来管理登录态和其他临时性的个人信息。然而随着现代互联网架构的发展趋势向微服务体系迈进,分布式部署变得越来越普遍,此时利用无状态特性的 Tokens 就显得尤为重要了——它们不仅能够跨越多个子域甚至完全独立的服务之间传递认证信息,而且减少了对共享内存资源的需求从而提高了系统的可伸缩性和性能表现。 #### 安全特性对比 由于 Sessions 需要依赖于服务器端维护的状态信息,因此容易受到诸如 CSRF 攻击的影响。相比之下,基于 Token 的身份验证方案更加灵活且具备更强的安全保障措施,比如可以通过设置较短的有效期来降低泄露风险,同时支持刷新机制以便长期保持有效连接而不必频繁重新输入密码等敏感资料。 ```python import jwt def create_token(user_id, secret_key): payload = { 'user_id': user_id, 'exp': datetime.utcnow() + timedelta(days=7), # 设置过期时间 } token = jwt.encode(payload, secret_key, algorithm='HS256') return token.decode('utf-8') # Python3 中返回的是bytes类型数据,需解码成str ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值