Cookie 属性配错会导致两种后果:要么被浏览器直接拒绝(如 SameSite=None 但缺 Secure),要么把敏感凭据暴露给 XSS 脚本(缺 HttpOnly)。
-
Max-Age(秒)
-
属性数量
-
告警条数
-
Secure(1=开)
-
Max-Age = 有效期天数 × 86400。__Host- 前缀要求同时满足:Secure 开启、Path=/、未设置 Domain,且值中不含空格。
四个属性各自防什么
| 属性 | 作用 | 不设置的后果 |
|---|---|---|
| Secure | 仅通过 HTTPS 发送 | 在 HTTP 请求中明文暴露,可被中间人窃取 |
| HttpOnly | 禁止 document.cookie 读取 | XSS 脚本可直接窃取会话凭据 |
| SameSite | 限制跨站请求是否携带 Cookie | CSRF 攻击可冒用用户身份发起请求 |
| Max-Age / Expires | 控制持久化时长 | 不设即为会话 Cookie,关浏览器即失效 |
SameSite 的三个取值
- Strict:任何跨站请求都不发送 Cookie。安全性最高,但从外部链接点进来时用户会显示未登录状态——体验有损。
- Lax:顶级导航的 GET 请求会发送(如从外部链接点进来),但 POST、iframe、AJAX 等跨站请求不发送。这是现代浏览器在未指定时的默认值,也是绝大多数场景的最佳平衡点。
- None:跨站也发送,必须同时设置 Secure,否则浏览器会直接拒绝该 Cookie。用于第三方嵌入场景(如 iframe 中的登录态、跨域 SSO)。
这里最常见的线上事故就是:为了支持 iframe 嵌入把 SameSite 设成 None,却忘了加 Secure,结果 Cookie 被浏览器静默丢弃,表现为"登录了但刷新就掉线",排查起来非常费时。
Cookie 前缀:让浏览器帮你做校验
| 前缀 | 强制要求 | 防御目标 |
|---|---|---|
| __Secure- | 必须设置 Secure,且来自 HTTPS 页面 | 防止在不安全信道被写入 |
| __Host- | 必须 Secure + Path=/ + 不得设置 Domain | 防止子域名或路径覆写 Cookie(子域注入攻击) |
__Host- 是防御"子域名 Cookie 覆写"的利器:如果攻击者控制了 evil.example.com,在没有 Zone 隔离的情况下可能往 example.com 写入同名 Cookie 覆盖你的会话。加上 __Host- 前缀后,浏览器会拒绝任何带 Domain 的同名 Cookie,攻击路径直接封死。
设置方式:优先服务端
Cookie 应当在 HTTP 响应头中设置,而不是用前端 JS:
Set-Cookie: session=abc123; Max-Age=604800; Path=/; Secure; HttpOnly; SameSite=Lax
原因很直接:HttpOnly 是 JS 无法设置的(document.cookie 写入的 Cookie 永远不带 HttpOnly),而且服务端能更可靠地管理密钥轮换与失效。前端 JS 设置 Cookie 只应用在确实无需安全保护的偏好项上(如主题色、语言选择)。
你可能还想问
哪些属性关系到安全?
仅加密通道传输、禁止脚本访问、限制跨站发送这几项最关键;缺失会让会话凭据更容易被窃取或滥用。
跨站场景为什么容易出问题?
严格策略可能拦住必要的跨站携带,放宽又会增加风险;要按业务是否真的需要跨站来选,而不是一律放开。
有效期怎么设?
会话凭据宜短、必要时用续期机制;过长的有效期在设备丢失或泄露时风险更大,按敏感度取舍。
速查在线工具箱