李锋镝的博客

  • 首页
  • 时间轴
  • 评论区显眼包🔥
  • 左邻右舍
  • 博友圈
  • 关于我
    • 关于我
    • 另一个网站
    • 我的导航站
    • 网站地图
    • 赞助
  • 留言
  • 🚇开往
Destiny
自是人生长恨水长东
  1. 首页
  2. 后端
  3. 正文

JWT、Cookie、Session、Token 区别与实战选型指南

2025年11月14日 286点热度 0人点赞 0条评论

在 Web 开发中,身份认证与状态管理是核心基础功能——用户登录、权限校验、会话保持等场景都离不开它们。JWT、Cookie、Session、Token 作为常用技术,常常被混淆使用。本文将从技术原理、核心特性、安全机制、实战场景四个维度,全面拆解四者的差异与关联,补充底层实现细节、安全优化方案和选型决策框架,帮你在面试与项目开发中精准应用。

一、核心概念与技术原理(从底层讲透)

1. Cookie:浏览器端的“小型数据容器”

Cookie 是浏览器提供的客户端存储机制,本质是服务器通过 HTTP 响应头下发、浏览器自动存储的小型文本数据(通常≤4KB),用于在客户端与服务器间传递状态信息。

核心原理

  1. 服务器通过 Set-Cookie 响应头设置 Cookie:

    Set-Cookie: sessionId=abc123; Expires=Wed, 20 Nov 2025 12:00:00 GMT; Path=/; Domain=example.com; HttpOnly; Secure; SameSite=Lax
  2. 浏览器将 Cookie 存储在本地(按域名隔离);
  3. 后续请求时,浏览器自动在 Cookie 请求头中携带对应域名的 Cookie,服务器通过解析 Cookie 获取状态。

关键属性与作用

属性 作用 安全意义
Expires/Max-Age 设置过期时间(Expires 是绝对时间,Max-Age 是相对秒数) 控制 Cookie 生命周期,避免永久存储
Path 限制 Cookie 生效的路径(如 /api) 减少不必要的 Cookie 携带,提升性能
Domain 限制 Cookie 生效的域名(如 example.com) 防止跨域名 Cookie 泄露,保障数据隔离
HttpOnly 禁止 JavaScript 访问 Cookie 防御 XSS 攻击(避免 Cookie 被脚本窃取)
Secure 仅在 HTTPS 协议下传输 Cookie 防止 HTTP 协议下的 Cookie 劫持
SameSite 限制跨站请求时 Cookie 携带(Strict/Lax/NONE) 防御 CSRF 攻击(避免跨站请求伪造身份)

核心特性

  • 自动携带:浏览器原生行为,无需开发者手动处理;
  • 容量受限:单条 Cookie 约 4KB,单个域名下通常限制 20-50 条;
  • 跨域限制:默认不支持跨域携带(需配合 CORS 与 SameSite=NONE);
  • 适用场景:存储 Session ID、用户偏好设置、CSRF Token 等小型数据。

2. Session:服务器端的“会话状态容器”

Session 是服务器为每个用户维护的“会话状态”,本质是服务器端存储的键值对数据,用于记录用户登录状态、权限信息等敏感数据,依赖 Cookie 传递会话标识。

核心原理

  1. 用户首次登录(提交账号密码),服务器验证通过后:
    • 创建 Session 对象(存储用户 ID、角色、登录时间等);
    • 生成唯一的 Session ID(如 abc123);
    • 通过 Set-Cookie 将 Session ID 下发给浏览器;
  2. 浏览器后续请求自动携带 Session ID Cookie;
  3. 服务器通过 Session ID 查找对应的 Session 对象,验证用户身份并获取状态。

存储方式与特性

存储方式 优点 缺点 适用场景
内存存储 读写速度快、无 IO 开销 服务器重启后丢失、不支持分布式部署 开发环境、单机小型应用
Redis 存储 高性能、支持分布式、可持久化 需额外部署 Redis 服务 生产环境、分布式系统
数据库存储 持久化强、支持复杂查询 读写速度慢、IO 开销大 对性能要求低、数据安全性要求高的场景

核心特性

  • 状态存储在服务器:敏感数据不暴露客户端,安全性高;
  • 依赖 Cookie 传递 ID:Session ID 是唯一标识,一旦泄露可能导致会话劫持;
  • 有状态设计:服务器需维护 Session 生命周期(过期清理、会话销毁);
  • 分布式挑战:多服务器部署时,需实现 Session 共享(如 Redis 集群)。

3. Token:广义的“身份凭证令牌”

Token(令牌)是一个广义概念,指用于身份认证的“一次性凭证”,本质是服务器签发的、可验证的字符串,用于证明用户身份或权限。

核心分类与作用

Token 类型 核心用途 生命周期
Access Token 访问受保护资源(如接口调用、页面访问) 短期有效(通常 15 分钟-2 小时),降低泄露风险
Refresh Token 重新获取 Access Token(无需重复登录) 长期有效(通常 7-30 天),需安全存储
验证码 Token 验证用户操作合法性(如登录验证码、短信验证) 瞬时有效(通常 5-10 分钟),一次性使用
CSRF Token 防御跨站请求伪造(如表单提交、接口调用) 会话级有效,与 Session 绑定

核心特性

  • 无状态设计:服务器无需存储 Token 本身,仅通过算法验证有效性;
  • 灵活性高:可通过 Cookie、HTTP 头部、请求体等多种方式传递;
  • 扩展性强:支持跨域、跨平台(Web、App、小程序)使用;
  • 安全性依赖实现:需通过加密、签名、过期机制保障防篡改与防泄露。

4. JWT:结构化的“自包含 Token”

JWT(JSON Web Token)是 Token 的标准化实现(遵循 RFC 7519 协议),本质是一种自包含、可验证的结构化令牌,通过 JSON 格式存储用户信息与元数据,无需服务器存储状态。

核心结构(三部分串联)

JWT 由 Header.Payload.Signature 三部分组成,通过 Base64URL 编码串联(非加密,仅编码):

  1. Header(头部):声明令牌类型与签名算法(如 HS256、RS256):

    {
     "alg": "HS256", // 签名算法(HMAC SHA256)
     "typ": "JWT"    // 令牌类型
    }
  2. Payload(载荷):存储核心数据(用户信息、元数据),包含标准字段与自定义字段:

    {
     "sub": "123456", // 标准字段:用户唯一标识
     "name": "张三",  // 自定义字段:用户名
     "role": "admin", // 自定义字段:用户角色
     "exp": 1753046400, // 标准字段:过期时间戳(秒)
     "iat": 1750454400  // 标准字段:签发时间戳(秒)
    }

    注意:Payload 仅 Base64URL 编码,不加密,禁止存储密码、密钥等敏感数据。

  3. Signature(签名):通过 Header 声明的算法,用密钥对编码后的 Header 和 Payload 签名,防止篡改:
    • HS256(对称加密):服务器用同一密钥签名与验证,密钥需严格保密;
    • RS256(非对称加密):用私钥签名、公钥验证,适合分布式系统(公钥可公开)。

核心原理

  1. 用户登录后,服务器验证账号密码,生成 JWT 并返回给客户端;
  2. 客户端存储 JWT(localStorage、Cookie 等);
  3. 访问受保护资源时,客户端在 HTTP 头部携带 JWT:

    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTYiLCJuYW1lIjoi5byg5LiJIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNzUzMDQ2NDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  4. 服务器验证 JWT 签名(确保未篡改)与过期时间,解析 Payload 中的用户信息,完成身份认证。

二、四者核心差异对比(维度全覆盖)

对比维度 Cookie Session Token(广义) JWT(结构化 Token)
存储位置 客户端(浏览器本地) 服务器端(内存/Redis/数据库) 客户端(浏览器/APP 本地) 客户端(浏览器/APP 本地)
数据形态 键值对文本(≤4KB) 键值对对象(无容量限制) 字符串(无固定格式) 结构化字符串(Header.Payload.Signature)
状态管理 无状态(服务器不存储,仅解析) 有状态(服务器维护会话状态) 无状态(服务器仅验证有效性) 无状态(自包含信息,无需服务器存储)
传递方式 浏览器自动携带(Cookie 请求头) 依赖 Cookie 传递 Session ID 手动携带(Header/请求体/URL) 手动携带(Authorization 头部为主)
安全性 低(易被 XSS/CSRF 攻击,需配置 HttpOnly 等属性) 高(敏感数据存储在服务器,仅暴露 Session ID) 中(依赖签名/加密机制) 中(签名防篡改,但 Payload 可解码)
跨域支持 弱(受 Domain/SameSite 限制) 弱(依赖 Cookie 跨域,需特殊配置) 强(无跨域限制,手动传递即可) 强(跨域、跨平台无缝支持)
分布式适配 无需适配(客户端自动处理) 需共享存储(如 Redis 集群) 无需适配(无服务器存储依赖) 无需适配(分布式系统天然友好)
吊销机制 支持(通过 Set-Cookie 设置过期/清空) 支持(服务器直接删除 Session 对象) 需自定义(如维护黑名单) 难(过期前无法直接吊销,需黑名单机制)
适用场景 存储 Session ID、CSRF Token、用户偏好 传统 Web 应用、需服务器维护状态的场景 通用身份认证(Web/APP/API) 前后端分离、微服务、跨平台应用

三、安全机制与风险防御(实战优化)

1. 各技术安全风险与防御方案

(1)Cookie 安全优化

  • 风险:XSS 攻击(脚本窃取 Cookie)、CSRF 攻击(跨站请求伪造)、Cookie 劫持;
  • 防御方案:
    • 必设 HttpOnly(禁止 JS 访问)与 Secure(仅 HTTPS 传输);
    • 配置 SameSite=Lax/Strict(限制跨站 Cookie 携带);
    • 敏感 Cookie 设置短过期时间,配合 Session 定期刷新;
    • 避免存储密码、令牌等核心敏感数据。

(2)Session 安全优化

  • 风险:Session ID 泄露(导致会话劫持)、Session 固定攻击;
  • 防御方案:
    • Session ID 采用随机强字符串(至少 16 位,包含大小写字母+数字+特殊字符);
    • 登录成功后重置 Session ID(防御 Session 固定攻击);
    • 短期过期(如 30 分钟无操作自动失效),结合客户端活动刷新 Session 生命周期;
    • 分布式部署时,用 Redis 存储 Session,配置密码与访问权限。

(3)JWT 安全优化

  • 风险:Payload 信息泄露、签名密钥泄露、无法吊销(过期前);
  • 防御方案:
    • 不存储敏感数据(如密码、手机号),仅存储用户 ID、角色等非敏感信息;
    • 采用 RS256 非对称加密(私钥签名、公钥验证),避免密钥泄露风险;
    • 缩短过期时间(如 Access Token 15 分钟),配合 Refresh Token 刷新;
    • 实现黑名单机制(用 Redis 存储已吊销的 JWT,验证时先查黑名单)。

2. 通用安全原则

  • 所有认证数据传输必须使用 HTTPS 协议,防止中间人攻击;
  • 敏感操作(如支付、密码修改)需二次验证,不依赖单一认证机制;
  • 定期清理过期数据(Cookie、Session、Token),减少攻击面;
  • 避免在 URL 中携带 Token/JWT(易被日志记录、缓存泄露)。

四、实战选型指南(场景化决策)

1. 传统 Web 应用(如管理系统、企业官网)

  • 选型:Session + Cookie
  • 理由:
    • 开发成本低(浏览器自动处理 Cookie 传递,无需手动适配);
    • 安全性高(敏感数据存储在服务器,仅暴露 Session ID);
    • 适合单体应用,无需复杂分布式配置;
  • 优化:
    • Session 存储用 Redis(避免服务器重启丢失);
    • Cookie 配置 HttpOnly + Secure + SameSite=Lax,防御常见攻击。

2. 前后端分离应用(如 Vue/React 前端 + 后端 API)

  • 选型:JWT + Refresh Token
  • 理由:
    • 跨域友好(前端独立部署,无需担心 Cookie 跨域问题);
    • 无状态设计(后端服务可水平扩展,无需共享存储);
    • 适配多端(Web/APP/小程序统一认证机制);
  • 实战流程:
    1. 用户登录,后端返回 Access Token(15 分钟过期)与 Refresh Token(7 天过期);
    2. 前端存储 Access Token(内存优先,避免 XSS 泄露)与 Refresh Token(Cookie 配置 HttpOnly);
    3. 访问 API 时,前端携带 Access Token;
    4. Access Token 过期时,前端用 Refresh Token 请求 /refresh-token 接口,获取新的 Access Token;
    5. Refresh Token 过期时,引导用户重新登录。

3. 微服务架构(多服务协同认证)

  • 选型:JWT + 统一认证中心
  • 理由:
    • 微服务无状态要求(JWT 自包含信息,无需服务间共享存储);
    • 统一认证(认证中心签发 JWT,所有微服务共用公钥验证);
    • 权限粒度可控(JWT Payload 可嵌入细粒度权限信息);
  • 优化:
    • 采用 RS256 非对称加密,认证中心持有私钥,微服务持有公钥;
    • 引入 API 网关,统一拦截 JWT 验证,减少微服务重复代码。

4. 小程序/APP 应用(跨平台场景)

  • 选型:Token(自定义签名)或 JWT
  • 理由:
    • 无浏览器 Cookie 依赖(APP/小程序无原生 Cookie 机制);
    • 手动传递灵活(通过请求头携带,适配各种网络环境);
  • 注意:
    • 存储 Token/JWT 时,避免明文存储(APP 可加密存储,小程序用 wx.setStorageSync 配合加密);
    • 定期刷新 Token,避免长期有效导致泄露风险。

五、常见误区与实战避坑

1. 误区 1:JWT 是加密技术

  • 纠正:JWT 核心是“签名防篡改”,而非“加密”——Payload 仅 Base64URL 编码,任何人都可解码查看,禁止存储敏感数据。
  • 解决方案:敏感信息需单独加密后再存入 Payload,或通过后端接口查询。

2. 误区 2:Session 比 JWT 更安全

  • 纠正:安全性取决于配置而非技术本身——Session 若 Session ID 泄露,攻击者可直接劫持会话;JWT 若配置强签名与短过期时间,安全性可媲美 Session。
  • 解决方案:Session 需保护 Session ID(Cookie 配置 HttpOnly/Secure),JWT 需用非对称加密+黑名单机制。

3. 误区 3:Cookie 已被淘汰

  • 纠正:Cookie 仍是最便捷的“自动传递”存储机制,适合存储 Session ID、CSRF Token 等,关键在于正确配置安全属性。
  • 解决方案:生产环境中,Cookie 必须配置 HttpOnly、Secure、SameSite 三大安全属性。

4. 误区 4:Token 越长越安全

  • 纠正:Token 安全性取决于签名算法与密钥强度,而非长度——过长的 Token 会增加传输成本,降低接口响应速度。
  • 解决方案:Token 仅包含必要信息,签名算法优先选择 RS256 而非复杂的自定义算法。

六、总结与选型决策框架

1. 核心结论

  • Cookie:不是认证技术,而是“客户端存储+自动传递”工具,常用于承载 Session ID 或 CSRF Token;
  • Session:服务器端状态管理方案,适合传统 Web 应用,需依赖 Cookie 传递标识;
  • Token:广义身份凭证,无固定格式,灵活性高,需自定义验证逻辑;
  • JWT:结构化 Token 标准,无状态、跨域友好,是前后端分离与微服务架构的首选。

2. 选型决策三步法

  1. 看架构:分布式/前后端分离/跨平台 → 选 JWT;传统单体 Web 应用 → 选 Session+Cookie;
  2. 看安全:需存储敏感会话状态 → 选 Session;仅需身份标识传递 → 选 JWT/Token;
  3. 看场景:需浏览器自动携带 → 选 Cookie+Session;需手动控制传递 → 选 JWT/Token。

最终选型没有绝对最优解,需结合业务场景、架构设计、安全要求综合判断——例如“JWT+Cookie(HttpOnly)”的组合,既能享受 JWT 的跨域与无状态优势,又能通过 Cookie 自动携带减少开发成本,同时提升安全性。

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/hou-duan/4578

相关文章

  • 双 Token 机制
  • 配置Jackson使用字段而不是getter/setter来序列化和反序列化
  • org.apache.ibatis.plugin.Interceptor类详细介绍及使用
  • JDK25模块级导入深度解析:Java导入机制的革命性进化
  • 深度解析 Disruptor:无锁队列的高性能实现与实践
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: Cookie JWT Session Token
最后更新:2025年11月14日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 上一篇
下一篇 >

文章评论

1 2 3 4 5 6 7 8 9 11 12 13 14 15 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 46 47 48 49 50 51 52 53 54 55 57 58 60 61 62 63 64 65 66 67 69 72 74 76 77 78 79 80 81 82 85 86 87 90 92 93 94 95 96 97 98 99
取消回复

我是人间惆怅客,知君何事泪纵横,断肠声里忆平生。

那年今日(04月14日)

  • 2010年:中国青海玉树大地震
  • 1894年:托马斯·爱迪生展示了其新发明活动电影放映机
  • 1629年:荷兰物理学家克里斯蒂安·惠更斯出生
  • 1578年:西班牙国王腓力三世出生
  • 605年:隋炀帝下令开凿大运河
  • 更多历史事件
最新 热点 随机
最新 热点 随机
Everything Claude Code 详细使用文档 配置Jackson使用字段而不是getter/setter来序列化和反序列化 这个域名注册整整十年了,十年时间,真快啊 Claude Code全维度实战指南:从入门到精通,解锁AI编程新范式 Apollo配置中心中的protalDB的作用是什么 org.apache.ibatis.plugin.Interceptor类详细介绍及使用
AI时代,个人技术博客的出路在哪里?使用WireGuard在Ubuntu 24.04系统搭建VPN这个域名注册整整十年了,十年时间,真快啊WordPress实现用户评论等级排行榜插件WordPress网站换了个字体,差点儿把样式换崩了做了一个WordPress文章热力图插件
开发者必懂的 AI 向量入门:从数学基础到实战应用 分代ZGC这么牛?底层原理是什么? 图解 | 原来这就是网络 使用springboot结合AI生成视频 Java枚举梳理总结一 Excel2016右键新建工作表,打开时提示“因为文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配。”的解决办法
标签聚合
设计模式 ElasticSearch docker 多线程 SpringBoot JAVA AI 分布式 MySQL JVM Spring SQL 架构 K8s IDEA WordPress 数据库 AI编程 Redis 日常
友情链接
  • Blogs·CN
  • Honesty
  • Mr.Sun的博客
  • 临窗旋墨
  • 哥斯拉
  • 彬红茶日记
  • 志文工作室
  • 懋和道人
  • 拾趣博客导航
  • 搬砖日记
  • 旧时繁华
  • 林羽凡
  • 瓦匠个人小站
  • 皮皮社
  • 知向前端
  • 蜗牛工作室
  • 韩小韩博客
  • 风渡言

COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

域名年龄

Theme Kratos Made By Dylan

津ICP备2024022503号-3

京公网安备11011502039375号