《别再混淆 Cookie 和 Session 了!这篇讲透存储 / 获取 / 区别的全流程指南》
一、Cookie/Session区别
| 对比维度 | Cookie | Session |
|---|---|---|
| 存储位置 | 客户端(浏览器 / APP 本地) | 服务器端(内存 / 数据库 / Redis) |
| 数据载体 | 键值对(Key-Value),字符串格式 | 键值对(Key-Value),可存任意 Java 对象 |
| 数据大小限制 | 单个 Cookie≤4KB,同一域名最多 20-50 个(浏览器限制) | 无默认大小限制(取决于服务器配置 / 存储介质) |
| 生命周期 | 可设置过期时间(Max-Age):1. 临时 Cookie(关闭浏览器失效);2. 持久 Cookie(到期自动删除) | 默认是 “会话级”(关闭浏览器 / 超时失效,默认 30 分钟);可手动设置过期时间 |
| 安全性 | 弱(客户端可篡改 / 删除 / 伪造,明文传输需注意) | 强(存储在服务器,客户端无法直接访问,仅通过 SessionID 关联) |
| 网络传输 | 每次 HTTP 请求都会自动携带(随请求头发送) | 仅传输 SessionID(通过 Cookie/URL 携带),核心数据不传输 |
| 依赖关系 | 可独立使用(无需 Session) | 通常依赖 Cookie 传递 SessionID(无 Cookie 时可通过 URL 重写) |
| 适用场景 | 存储少量不敏感数据:- 记住登录状态(勾选 “7 天内自动登录”);- 保存用户偏好(主题 / 语言);- 跟踪用户行为(埋点标识) | 存储敏感 / 大量数据:- 用户登录信息(用户名 / 权限);- 购物车数据;- 会话期间的临时状态 |
- ✅ 关联逻辑:Cookie 存 SessionID → 浏览器带 Cookie(含 SessionID)请求 → 服务器通过 SessionID 找对应 Session 数据。
- ✅ 浏览器不是 “无脑发所有 Cookie”,而是按域名匹配发送:比如你访问
www.baidu.com,浏览器只会发送 “归属baidu.com域名” 的 Cookie(含 SessionID),不会把taobao.com的 Cookie 发过去;
完整逻辑:
- 客户端请求登录 → 后端校验账号 + 加密后的密码 → 验证通过后:
- 服务器创建 Session,存入 “用户 ID / 权限”(不存密码),生成唯一 SessionID;
- 服务器通过
Set-Cookie响应头,把 SessionID 存到客户端 Cookie 中(可设置 Cookie 的HttpOnly(防 JS 篡改)、Secure(仅 HTTPS 传输)属性加固);
- 后续请求时:
- 浏览器按域名匹配,把含 SessionID 的 Cookie 自动带到服务器;
- 服务器校验 Cookie 的合法性(IP/UA)→ 用 SessionID 找到对应的 Session → 读取用户身份数据返回;
- 数据存储规则:
- Cookie:存 “非敏感、少量、需长期保存” 的数据(如主题颜色、记住登录的标识),通过
Max-Age设置长期有效; - Session:存 “敏感、临时、会话级” 的数据(如用户 ID、权限),默认超时销毁,服务器主动管控安全性。
- Cookie:存 “非敏感、少量、需长期保存” 的数据(如主题颜色、记住登录的标识),通过
2.关键区别的通俗类比
把 Cookie 和 Session 类比成 “酒店入住流程”:
-
Cookie = 客人手里的 “房卡”:
- 存储在 “客人手里”(客户端),是服务器(酒店)给的 “凭证”;
- 房卡上只有 “房间号”(SessionID)等简单信息,没有客人的详细数据;
- 每次进出酒店(HTTP 请求),客人必须带上房卡(自动携带 Cookie),酒店才认人;
- 房卡可以弄丢 / 伪造(客户端可篡改 Cookie),所以酒店需要验证房卡真伪(后端校验 Cookie)。
-
Session = 酒店前台的 “客人登记表”:
- 存储在 “酒店前台”(服务器),记录客人的详细信息(姓名 / 身份证 / 入住时间);
- 登记表的 “编号” 就是房卡上的 “房间号”(SessionID),一一对应;
- 客人不用带登记表(核心数据不传输),只带房卡(SessionID),前台就能查到对应的记录;
- 登记表由酒店保管(服务器控制),客人无法修改,安全性更高。
3.核心区别的深度拆解
3.1 存储位置:决定了安全性和访问权限
- Cookie 在客户端:浏览器会把 Cookie 存在本地文件(比如 Chrome 的 Cookie 数据库),用户可以手动在浏览器开发者工具(Application→Cookies)中修改、删除 Cookie(比如把
username=zhangsan改成username=lisi),所以不能存敏感数据(如密码、银行卡号)。 - Session 在服务器:Session 是服务器内存中的一个 “哈希表”(或存在 Redis、数据库),客户端完全无法直接访问,只能通过 SessionID 间接获取数据,所以可以存敏感数据(如用户权限、登录状态)。
3.2 网络传输:影响性能和数据安全性
- Cookie 每次都传:比如你存了 10 个 Cookie,每个请求都会把这 10 个 Cookie 都带到服务器,增加请求体积(尤其 Cookie 多的时候),影响传输速度;且 Cookie 是明文传输(除非用 HTTPS 加密),容易被拦截篡改。
- Session 只传 SessionID:核心数据(如用户信息)都存在服务器,客户端只需要在请求中带一个 SessionID(通常存在 Cookie 里),传输体积小,且 SessionID 是随机字符串(如
3F9A2B7D),即使被拦截,没有服务器的 Session 数据也没用。
3.3 生命周期:决定 “状态保持多久”
- Cookie 的生命周期可手动设置:
- 不设置
Max-Age:临时 Cookie,关闭浏览器就失效(比如登录时没勾选 “记住我”,登录状态只在当前浏览器窗口有效); - 设置
Max-Age=86400(秒):持久 Cookie,会存在本地,1 天后自动删除(比如勾选 “7 天内自动登录”,就是设置Max-Age=604800)。
- 不设置
- Session 的生命周期默认是 “会话级”:
- 关闭浏览器:客户端的 SessionID(存在 Cookie 里)会失效,下次打开浏览器再请求,服务器会认为是新用户,创建新的 Session;
- 服务器超时:即使不关闭浏览器,服务器超过默认时间(通常 30 分钟)没收到请求,会自动销毁 Session(避免占用内存);
- 手动销毁:调用
session.invalidate()(比如用户退出登录时,删除 Session 数据)。
3.4 依赖关系:不是 “必须绑定使用”
很多人以为 Cookie 和 Session 必须一起用,其实不是:
- 只用 Cookie:比如存储用户的主题偏好(深色 / 浅色模式),直接把
theme=dark存在 Cookie 里,服务器读取 Cookie 就能用,不需要 Session; - 只用 Session:比如通过 URL 重写(把 SessionID 拼在 URL 后面,如
http://xxx.com?JSESSIONID=3F9A2B7D)传递 SessionID,不用 Cookie(适合浏览器禁用 Cookie 的场景); - 一起用(最常见):SessionID 存在 Cookie 里,客户端每次请求带 Cookie 中的 SessionID,服务器通过 SessionID 找到对应的 Session,这种方式既安全又方便。
4.总结:怎么选?
- 存少量、不敏感、需要长期保持的数据 → 用 Cookie(如记住登录状态、用户偏好);
- 存大量、敏感、仅会话期间需要的数据 → 用 Session(如用户权限、购物车);
- 实际开发中:大多是 “Cookie 存 SessionID + Session 存核心数据” 的组合,既安全又能保持会话状态。
二、获取Cookie/Session
1.核心背景:HTTP 的 “无状态” 特性
- HTTP 协议默认是 “无状态” 的:客户端与服务器的每次通信相互独立,服务器无法直接识别 “同个客户端的多次请求”。
- 实际需求:需识别请求间的关联(如登录后,服务器能识别后续请求的登录状态),因此需要 Cookie 和 Session 机制。
2.Session 的基础:“会话” 的概念
- 会话的含义
- 字面义:对话、交互的过程;
- 计算机领域:客户端与服务器之间的 “持续请求 - 响应周期”,从客户端首次请求开始,到客户端主动结束 / 服务器超时无请求时终止(类比 “打客服电话:通话过程是一个会话,挂断则结束”)。
- 会话的核心作用服务器需区分不同客户端的请求,因此要记录 “每个会话与对应用户信息的关联关系”。
2.1Session 的工作流程(多客户端场景)
当多个客户端(A/B/C)向服务器发起请求时:
- 服务器为每个客户端单独创建一个 Session 对象(互不干扰);
- 每个 Session 对应唯一的 “SessionID”,用于标识客户端身份;
- 后续客户端请求时,通过 SessionID 关联到对应的 Session,从而识别用户信息。

2.2Session 的本质:服务器端的 “哈希表”
Session 是服务器存储用户信息的键值对结构:
| 结构元素 | 说明 |
|---|---|
| Key | SessionID(服务器生成的唯一字符串,也可称为 “token”) |
| Value | 用户信息(可自定义格式,如 id、用户名、年龄等) |

- SessionID-1 对应 Value:
{id:5, userName:zhangsan, age:18} - SessionID-4 对应 Value:
{id:6, userName:lisi, age:19}
SessionID 是服务器生成的唯一字符串,在登录流程中也可称为 “Token”:
- SessionID 仅作为身份标识;
- 广义 Token 可能包含额外信息(如时间、签名),但本质都是 “客户端身份凭证”。

- 当⽤⼾登陆的时候,服务器在Session中新增⼀个新记录,并把sessionId返回给客⼾端.(通过 HTTP响应中的Set-Cookie字段返回).
- 客⼾端后续再给服务器发送请求的时候,需要在请求中带上sessionId.(通过HTTP请求中的 Cookie字段带上).
- 服务器收到请求之后,根据请求中的sessionId在Session信息中获取到对应的⽤⼾信息,再进⾏后续操作.找不到则重新创建Session,并把SessionID返回.

Session默认是保存在内存中的.如果重启服务器则Session数据就会丢失.
3.Cookie 与 Session 的工作流程(以登录为例)
通过 “医院就诊卡” 的类比,流程如下:
- 获取 “令牌”(Cookie)
- 客户端请求登录页面→服务器返回页面;
- 客户端提交账号密码→服务器验证通过后,生成 “令牌”(即 SessionID),并通过 Cookie 将令牌发送给客户端。
- 使用 “令牌” 关联状态(Session)
- 客户端后续请求时,自动携带 Cookie 中的 “令牌”;
- 服务器通过 “令牌”(SessionID),找到对应的用户信息(存储在服务器端的 Session 中),从而识别用户身份。
4.获取Cookie
Cookie是可以伪造的,也就是不安全的,所以使⽤Cookie时,后端需要进⾏ Cookie校验
4.1传统获取Cookie

4.2简洁获取Cookie

5.获取Session
Session 的核心逻辑:先存储再获取
Session 是服务器端机制,需先将数据存入 Session,才能后续读取。其操作依赖HttpServletRequest对象,底层通过请求中 Cookie 携带的 SessionID关联对应的 Session 对象(开发者无需手动处理 SessionID,getSession()方法会自动完成关联)。
5.1Session存储

request.getSession():自动关联 / 创建 Session,是操作 Session 的入口;session.setAttribute(key, value):将数据以键值对形式存入当前 Session。- 这个代码中看不到SessionId这样的概念的.
- getSession操作内部提取到请求中的Cookie⾥的 SessionId,
- 然后根据SessionId获取到对应的Session对象,Session对象⽤HttpSession来描述

5.2Session 的获取方式(两种getSession方法)
| 方法签名 | 功能说明 |
|---|---|
HttpSession getSession(boolean create) |
参数 参数 |
HttpSession getSession() | 等价于getSession(true),默认自动创建 Session。 |
session.setAttribute(String name, Object value):将任意对象以指定名称绑定到 Session 中,是 Session 存储数据的核心方法;- 底层关联逻辑:
getSession()会自动读取请求 Cookie 中的 SessionID,找到服务器中对应的HttpSession对象(开发者无需感知 SessionID 的传递)。
5.3Session读取
读取Session可以使⽤HttpServletRequest

| 代码片段 | 作用 |
|---|---|
request.getSession(false) | 获取 Session,若不存在则返回null(避免无意义的 Session 创建) |
session.getAttribute("username") | 读取 Session 中key=username对应的 value,若不存在则返回null;返回值为Object类型,需强转为实际数据类型(如 String) |
- 先执行 Session 存储:访问
/setSess接口,服务器创建 Session 并存入username=java,同时将 SessionID 通过 Cookie 返回给客户端; - 再执行 Session 读取:访问
/getSess接口时,客户端自动携带 SessionID 的 Cookie → 服务器通过getSession(false)找到对应的 Session → 读取到username=java→ 返回结果username: java; - 若 Session 不存在:若未执行
/setSess直接访问/getSess,session为null,最终返回username: null。
5..4简化 Session 数据读取的两种方式
方式 1:@SessionAttribute 注解(最简洁)

- 核心作用:通过
@SessionAttribute注解,直接将 Session 中指定 key 的值绑定到方法参数,无需手动获取HttpSession。 - 参数说明:
value = "username":指定要读取的 Session 的 key;required = false:表示该 Session 数据是可选的,不存在时参数为null(默认required=true,缺失会抛异常)。
- 运行效果:若 Session 中存在
username=java,返回username: java;若不存在,返回username: null。
方式 2:直接注入 HttpSession 对象

- 核心作用:Spring MVC 自动将当前请求关联的
HttpSession对象注入方法参数,替代原生的request.getSession()。 - 注意点:
- 注入的
session等价于request.getSession()(Session 不存在时会自动创建); - 读取数据时需手动调用
getAttribute()并强转类型(与原生操作逻辑一致)。
- 注入的
三种 Session 读取方式对比
| 方式 | 实现方式 | 优点 | 缺点 |
|---|---|---|---|
原生方式(request.getSession()) | 通过HttpServletRequest获取 Session | 完全自主控制 Session 创建时机 | 代码冗余,需手动判空 |
@SessionAttribute注解 | 直接绑定参数 | 代码最简洁,无需手动操作 | 仅适用于读取单个 Session 数据 |
注入HttpSession对象 | 直接注入 Session 对象 | 兼顾简洁性与灵活性 | Session 不存在时会自动创建 |
6.获取Header
方式 1:原生方式(通过 HttpServletRequest)

- 核心逻辑:利用
HttpServletRequest提供的getHeader(String key)方法,根据请求头的 Key 读取对应的值; - 示例效果:读取
User-Agent请求头(标识客户端浏览器 / 设备信息),返回结果如userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...; - 特点:原生 Servlet API,兼容性强,但代码相对冗余。
方式 2:简洁方式(@RequestHeader 注解)

- 核心逻辑:通过
@RequestHeader注解,直接将指定 Key 的请求头值绑定到方法参数,无需手动调用getHeader; - 注解说明:
@RequestHeader("User-Agent")中的参数是请求头的 Key,与原生方式的getHeader参数一致; - 示例效果:与原生方式完全一致,返回相同的
User-Agent信息。
两种方式对比
| 方式 | 实现方式 | 优点 | 缺点 |
|---|---|---|---|
| 原生方式(HttpServletRequest) | 调用getHeader方法 | 兼容所有 Servlet 环境 | 代码冗余,需依赖 Request 对象 |
@RequestHeader注解 | 直接绑定方法参数 | 代码简洁,无冗余模板代码 | 仅适用于 Spring MVC 环境 |
请求头的作用:
以User-Agent为例,请求头是 HTTP 协议中客户端向服务器传递附加信息的载体,常见的请求头还包括Content-Type(请求体类型)、Authorization(身份认证)等,读取请求头是 Web 开发中获取客户端环境信息的基础操作。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)