Cookie 与 Session 入门

从无状态 HTTP 出发理解 Cookie 与 Session 的分工、会话固定、会话劫持等风险,以及登录后轮换 session id、HttpOnly、Secure、SameSite 等防御手段。

写在前面:合法学习边界

本文讲解会话机制的原理与防御。不要拿真实网站、企业系统去测试会话固定、会话劫持或伪造 Cookie。所有验证必须在自建靶场或明确授权的测试环境中完成。

一、为什么 HTTP 需要“会话”

HTTP 本身是无状态的,每次请求都是独立的。服务器收到两次请求,默认不知道是不是同一个人。

但真实业务需要“记住登录状态”,所以出现了会话机制。常见分工是:

1
2
Cookie:浏览器保存的小片段,随请求自动携带
Session:服务端保存的状态,客户端只拿一个标识

理解这两者,才能看懂“登出无效”“换个浏览器又要登录”“会话被劫持”这些问题。

二、Cookie 是什么

Cookie 是服务器通过 Set-Cookie 下发给浏览器的小数据块,浏览器之后会在同域请求里带上它。

一次典型交互:

1
2
服务器:Set-Cookie: sessionid=abc123; Path=/; HttpOnly; Secure; SameSite=Lax
浏览器:Cookie: sessionid=abc123

Cookie 上常见的属性直接决定安全边界:

1
2
3
4
5
Domain / Path:哪些地址会带这个 Cookie
HttpOnly:禁止 JS 读取,防 XSS 直接偷走
Secure:仅 HTTPS 下传输
SameSite:控制跨站请求是否携带
Expires / Max-Age:有效期

如果 Cookie 里直接放了用户名、角色甚至明文密码,那就是把信任交给了客户端,风险很大。

三、Session 是什么

Session 通常放在服务端内存、Redis 或数据库里。客户端只持有 session id,服务端拿这个 id 去查状态。

典型流程:

1
2
3
4
登录成功
服务端创建会话,生成 session id
Set-Cookie 返回给客户端
后续请求带 session id,服务端校验

这里最关键的一句话:Session 内容在服务端,客户端只有一把钥匙。如果把用户身份放在客户端 Cookie 里自己拼,等于把门锁交给了别人。

四、常见风险

1. 会话固定

登录前和登录后 session id 没变。攻击者可以先给自己发一个 session id,诱导用户用它登录,登录后攻击者复用同一个 id。

防御重点是:登录成功后必须重新生成 session id

2. 会话劫持

session id 被偷,攻击者就能冒充用户。偷取途径包括:

1
2
3
XSS 偷 Cookie(没 HttpOnly)
HTTP 明文传输(没 Secure)
日志、Referer、第三方脚本泄露

3. 会话过期管理不当

会话永远不过期、宽限期过长、登出只清前端不清理服务端,都会放大风险。

4. 并发登录与暴力破解

没有限制单账号登录会话数量、没有失败次数限制,容易被撞库或滥用。

五、防御建议

1
2
3
4
5
6
登录成功后轮换 session id
Cookie 加 HttpOnly、Secure、SameSite=Lax/Strict
设置合理过期时间并支持服务端失效
敏感操作要求二次认证
限制异常登录和会话复用
敏感 Cookie 用独立隔离(如同源策略 + 独立域名)

六、报告中的正确写法

示例:

1
2
3
发现:登录成功后 session id 未重新生成,Cookie 未设置 HttpOnly 且站点允许 HTTP 访问。
风险:可能被会话固定、XSS 窃取会话导致冒充登录态。
建议:登录后重新生成 session id;Cookie 增加 HttpOnly、Secure、SameSite;强制 HTTPS。

写报告时要把“怎么验证的、影响面、修复建议”说清楚,而不是只写“会话不安全”。

七、小结

Cookie 只是标识,Session 才是状态。真正要保护的是服务端会话,而不是客户端那张“钥匙”。把这两者分开理解,会话固定、劫持、过期这些问题就有了统一的解释。