今天聚焦 HTTP 状态码、Cookie、Session、Token 机制,将理论与动手观察结合,并持续渗透安全思维。
第一周·周四:HTTP 状态码与 Cookie、Session、Token 机制
🎯 今日学习目标(达成效果)
- 能独立说出HTTP 状态码的五大分类及每类代表含义,并准确描述 200、301、302、304、400、403、404、500、502、503 等常见状态码的使用场景;
- 能用浏览器开发者工具快速定位一次请求的状态码、响应头中的
Set-Cookie和请求头中的Cookie; - 能用自己的话解释为什么 HTTP 是无状态的,以及 Cookie/Session 如何解决状态问题;
- 能画出并讲解基于 Session 的认证流程和基于 Token 的认证流程;
- 能从安全视角指出 Cookie 的 HttpOnly、Secure 属性的作用,以及 Session 劫持、CSRF 攻击与 Token 的关系;
- 能清晰回答“301 和 302 有什么区别”、“Token 为什么比 Session 更适合移动端”。
📘 一、HTTP 状态码:服务端对请求结果的“加密语言”
每一个 HTTP 响应都会携带一个三位数字的状态码,它能让客户端(浏览器、爬虫、渗透工具)立即了解请求的处理结果。
1. 状态码分类
| 状态码范围 | 类别 | 含义 | 典型示例 |
|---|---|---|---|
| 1xx | 信息性状态码 | 请求已接收,继续处理 | 101 Switching Protocols(WebSocket 升级) |
| 2xx | 成功 | 请求已成功被接收、理解、接受 | 200 OK、201 Created、204 No Content |
| 3xx | 重定向 | 需要客户端进一步操作才能完成请求 | 301 永久重定向、302 临时重定向、304 Not Modified |
| 4xx | 客户端错误 | 请求包含语法错误或无法被满足 | 400 Bad Request、403 Forbidden、404 Not Found |
| 5xx | 服务器错误 | 服务器在处理请求时发生错误 | 500 Internal Server Error、502 Bad Gateway、503 Service Unavailable |
安全视角:状态码本身就是信息泄漏的源头。例如,403 可能告知攻击者“资源存在但没有权限”,404 则可能说明资源不存在或路径错误;302 可能泄露内部跳转逻辑;500 报错可能爆出服务器路径、代码行数等敏感信息。在渗透测试信息收集阶段,状态码分析是基础。
2. 必须吃透的常见状态码
- 200 OK:请求成功,正常返回数据。GET 返回所请求资源,POST 返回操作结果。
- 301 Moved Permanently:永久重定向。服务器告知客户端,请求的资源已被永久移动到
Location头部指定的新 URL。浏览器会缓存这个重定向,后续请求旧地址时直接使用新地址,不再询问服务器。搜索引擎也会将权重转移到新 URL。 - 302 Found(或Moved Temporarily):临时重定向。资源只是暂时移动到新 URL,客户端不应该缓存,下一次请求仍应访问原 URL。常用于未登录用户跳转到登录页,登录后再跳回。
- 304 Not Modified:客户端发送带
If-Modified-Since或If-None-Match头的条件请求,服务器确认资源未修改,返回 304 且不带响应体,客户端可直接使用本地缓存。大幅提升性能。 - 400 Bad Request:客户端请求有语法错误,服务器无法理解。比如请求头过大、格式错误。
- 403 Forbidden:服务器理解了请求,但拒绝执行。通常权限不足,但资源存在(与 401 不同,401 表示需要认证)。
- 404 Not Found:请求的资源不存在。渗透中常通过访问某些敏感路径(如
/admin)判断是否为 403 或 404,以此猜测后端目录结构。 - 500 Internal Server Error:服务器内部处理出错,通常由代码异常、配置错误等引发。攻击者可能通过构造异常输入触发 500,从而推断注入点或服务端语言。
- 502 Bad Gateway:作为网关或代理的服务器从上游服务器收到无效响应。常出现在 Nginx 反向代理后端服务宕机时。
- 503 Service Unavailable:服务器暂时无法处理请求(过载或维护),通常过一段时间恢复。运维保障需关注。
3. 重定向的实战观察
打开浏览器开发者工具 Network 面板,勾选“Preserve log”,访问一个会自动跳转的 HTTP 站点(如许多网站会将 http 跳转到 https),你会看到:
- 第一个请求返回301 或 302,响应头包含
Location: https://... - 浏览器紧接着自动发起第二个请求到新 URL,状态码 200。
尝试用 curl 分别观察 301 和 302:curl -v http://某个会重定向的地址,加上-L参数看自动跟随。
📘 二、Cookie:解决 HTTP 无状态的小标签
为什么需要 Cookie?
HTTP 本身不保存任何请求间的关系,服务器不能自动识别“刚才请求页面的用户”与“现在登录的用户”是同一个人。Cookie 是服务器委托浏览器保存在客户端的一小段文本数据,下次请求同一站点时,浏览器会自动带上它,从而让服务器能识别连续会话。
1. Cookie 的工作流程
- 客户端首次请求服务器(如登录页面)。
- 服务器验证用户身份后,在响应中加入
Set-Cookie头部:Set-Cookie: sessionid=abc123; Path=/; HttpOnly; Secure - 浏览器收到该头部,会将
sessionid=abc123及其属性存入本地 Cookie 存储区。 - 之后客户端每次请求该域时,浏览器都会在请求头自动附加
Cookie: sessionid=abc123。 - 服务器读取 Cookie 中的 sessionid,到服务端存储中查找对应的用户信息,识别用户身份。
2. Cookie 的关键属性(安全相关)
- Domain / Path:限定 Cookie 的作用域。若 Domain 设置过宽可能引发安全隐患,比如子域名之间不必要地共享 Cookie。
- Expires / Max-Age:控制 Cookie 有效期,未设置则为会话 Cookie,关闭浏览器即失效。
- HttpOnly:极其重要。若设置为 true,浏览器将禁止 JavaScript(如
document.cookie)读取该 Cookie。这是防御 XSS 窃取会话 Cookie 的第一道防线。 - Secure:若设置为 true,浏览器只会在 HTTPS 加密连接上传输该 Cookie,防止中间人嗅探。
- SameSite:防御 CSRF 攻击的新属性。
SameSite=Strict禁止所有跨站请求携带 Cookie;SameSite=Lax允许部分(如导航链接)携带;None则无限制(需配合 Secure)。
安全视角总结:
- 没有 HttpOnly 的会话 Cookie 一旦被 XSS 攻击获取,攻击者就能接管用户会话。
- 没有 Secure 的 Cookie 在 HTTP 下可能被 ARP 欺骗等手段截获。
- SameSite 属性可直接削减 CSRF 攻击面,但老版本浏览器可能不支持。
📘 三、Session:服务端维护的用户会话
1. 原理
Session 是一种服务端的状态保持方案。用户登录后,服务器生成一个全局唯一的 SessionID(随机、不可预测),并建立一块内存/数据库空间保存该 ID 对应的用户信息。然后将 SessionID 通过Set-Cookie发送给浏览器,浏览器每次请求带着这个 SessionID,服务器用它查找会话数据。
典型流程:
- 用户提交登录表单 → 服务器验证密码 → 创建 Session,存储
user_id、角色等信息 → 响应Set-Cookie: SESSIONID=随机串 - 后续请求:浏览器自动带 Cookie → 服务器根据 SessionID 查找 Session 数据,确认用户身份。
2. 常见安全风险
- Session 劫持:攻击者通过 XSS、网络嗅探、日志泄露等方式获取他人 SessionID,并在自己浏览器中伪造 Cookie,冒充用户。防御:HttpOnly、Secure、HTTPS、及时销毁过期 Session。
- Session 固定攻击:攻击者先获取一个合法 SessionID(如访问网站获得),然后诱导受害者使用这个固定的 ID 登录(如通过 URL 传递),之后攻击者就可以用此 ID 访问受害者的会话。防御:用户登录后立即更换 SessionID。
- Session 过期与销毁:没有及时注销的 Session 可能被复用,需要设置合理超时和手动登出时清除服务端会话。
📘 四、Token 认证:无状态的身份证明
对于移动端、前后端分离、微服务等场景,Session 存在扩展性差、不适合跨域等问题。Token 是一种更灵活的方案,尤其是JWT(JSON Web Token)。
1. Token 工作原理
- 用户登录成功后,服务器根据用户信息、过期时间等生成一个 Token,并用密钥对其进行签名(或加密)。Token 本身包含了用户身份信息,自包含。
- 服务器将 Token 直接返回给客户端(通常放在响应体 JSON 中)。
- 客户端保存 Token(如 localStorage、移动端本地存储),并在后续请求中将 Token 放在
Authorization头部(Bearer Token)或 POST 参数中。 - 服务器收到 Token 后,只需验证签名是否有效、是否过期,而无需查询数据库或会话存储,即可识别用户。因此它是无状态的。
2. JWT 结构
JWT 由三段 Base64 字符串组成,用.分隔:
- Header:声明类型和签名算法(如
{"alg":"HS256","typ":"JWT"})。 - Payload:存放实际数据(用户 id、过期时间、签发者等),称为声明(Claims)。注意:Payload 仅 Base64 编码,非加密,任何人可见,绝不能存放密码等敏感信息!
- Signature:使用 Header 中声明的算法,对 Header 和 Payload 进行签名,防止篡改。
3. 为什么 Token 比 Session 更适合移动端?
- 扩展性:Session 存储在服务器内存或数据库,大型分布式架构需要共享 Session,增加复杂度。Token 自包含,任何服务实例只要能验证签名就可识别用户,更契合无状态的 API 设计。
- 跨域便捷:Cookie 受同源策略和域名限制,移动端或跨域 API 调用不一定走浏览器 Cookie 机制,Token 放在 Header 中天然跨域。
- 无需依赖浏览器:移动 App 没有浏览器那样的 Cookie 自动管理,手动管理 Token 更直接,也可安全存储于设备安全区域。
- 多服务适配:微服务架构中,每个服务仅需公钥即可验签 Token,无需集中式会话存储。
4. Token 的安全注意
- 签名密钥必须高强度保护:若对称密钥泄露,攻击者可伪造任何用户 Token。
- Payload 加密不是必选项:必要时可使用 JWE(加密 JWT)或内部加密,但常见实现仍是签名而非加密,务必不要让 JWT 承载密码。
- 存储位置:浏览器端若将 Token 存于 localStorage 可能遭受 XSS 窃取,存于 HttpOnly Cookie 又无法自定义 Authorization 头,需要权衡。最佳实践中可使用 BFF 模式,或使用仅 HttpOnly 的 Cookie 但仍携带 CSRF Token。
- 过期与刷新:设计短期有效的 Access Token 和长期 Refresh Token,减少泄露风险。
✍️ 五、动手实践:用开发者工具和 curl 观察状态码、Cookie
实践 1:追踪一次重定向的状态码
打开终端,访问一个已知会跳转的 URL(建议自己搭建或使用公开测试站):
curl-vhttp://www.baidu.com2>&1|grep-E"HTTP|Location"你会看到服务器返回HTTP/1.1 302 Found和Location: ...。加上-L再试试:curl -L -v http://www.baidu.com,观察是否自动跟随。
实践 2:观察 Set-Cookie 和 Cookie 发送
- 打开浏览器隐私窗口,F12 → Network → 勾选“Preserve log”。
- 访问一个需要登录的网站(例如
http://testphp.vulnweb.com这类练习站),先观察首页的响应头,可能会看到Set-Cookie设置会话。 - 输入任意用户名密码提交登录(或注册),观察登录请求的响应,查找
Set-Cookie中设置的会话 ID。 - 登录后刷新页面,观察此时请求头中的
Cookie字段已自动带上之前设置的会话 ID。 - 重点检查:Set-Cookie 是否带有
HttpOnly和Secure标志。
实践 3:手动模拟 Set-Cookie 与 Cookie 发送
用 curl 手动携带 Cookie:
curl-v-b"sessionid=abc123"http://example.com查看请求头是否出现Cookie: sessionid=abc123。
📝 六、课后测试题与解析
测试题 1:301 和 302 重定向有什么区别?分别适用于什么场景?
参考答案:
- 301 永久重定向:表示资源已被永久移动到新地址。浏览器会缓存此重定向信息,之后对原 URL 的请求会自动转为新 URL,不再询问服务器。搜索引擎也会将权重转移到新 URL。适用于网站域名永久迁移、HTTP 永久升级到 HTTPS。
- 302 临时重定向:表示资源只是临时移动到新地址。浏览器不应缓存,下次请求还会发送到原 URL 让服务器再次决策。适用于网站维护时的临时跳转、未登录用户重定向到登录页(登录后返回原页面,不能缓存)。
安全角度补充:302 曾被一些攻击利用(如 302 跳转劫持),现在很多浏览器为避免歧义,对 302 的实际缓存行为趋于保守。
测试题 2:为什么 Token 认证比 Session 更适合移动端应用?
参考答案:
- 无状态:Token 自包含用户信息,服务器不需要存储会话数据,轻松水平扩展,适合移动端后端常见的分布式 API 服务。
- 跨域通用:Token 放在 HTTP Header 中,不受浏览器同源策略及 Cookie 域名限制,适合移动 App 和各种跨域 API 调用。
- 不依赖浏览器 Cookie 机制:移动 App 没有自动管理 Cookie 的能力,使用 Token 手动存放和发送更清晰可控,也能利用设备安全存储(如 Keychain)。
- 性能:省去服务端查数据库/缓存获取会话的步骤,只验签即可,减少延迟。
- 但也要注意移动端的 Token 安全存储问题,以及必须使用 HTTPS 防止令牌被窃。
✅ 今日学习效果自检清单
- 我能默写 5 类状态码范围及含义,并举例说明每类的典型状态码
- 我能解释 301 和 302 的关键区别(缓存与否)
- 我知道 403 与 401 的差异(已认证但无权 vs 未认证)
- 我能画出基于 Cookie 的 Session 认证流程(登录→Set-Cookie→后续请求带 Cookie)
- 我明白 HttpOnly 和 Secure 属性分别防御什么攻击(XSS 窃取、中间人嗅探)
- 我能对比 Session 和 Token 的优缺点,说出 Token 适合移动端的原因
- 我在 Network 面板中成功找到 Set-Cookie 和 Cookie 头部,并观察到重定向的状态码
⚠️ 阶段避坑重点
- 不要混淆 301 和 302 的缓存行为:面试常考,实战中不正确使用会引发 SEO 或功能问题。
- 不要把“Token 更适合移动端”理解成“Token 绝对安全”:Token 也需要防泄漏、防重放,且不应在 Payload 存放隐私信息。
- 不要忽略 Cookie 属性:看响应头时,务必检查 HttpOnly 和 Secure,这是你以后做安全审计的基本功。
- 不要死记状态码数字:要结合场景理解。比如看到 304,你要知道这是缓存相关;看到 502,知道是网关错误,通常后端服务挂了。
明天(周五)我们将学习Wireshark 抓包实操,把今天学到的状态码、Cookie、重定向全部放到真实抓包环境里验证,用数据包还原整个交互过程,请务必保留一些实验用的网站或今天的请求记录。