Cookie 的作用域
Cookie 的共享不是由 Java 代码直接控制的,而是通过 HTTP 响应头中的 Set-Cookie 字段,以及浏览器在后续请求中携带的 Cookie 请求头来实现的,关键在于 Set-Cookie 头中的几个属性:
Domain(域):这是控制 Cookie 在哪些域名下可用的核心属性。Path(路径):在指定域名下,进一步限制 Cookie 在哪些 URL 路径下可用。Secure(安全):限制 Cookie 只能通过 HTTPS 连接发送。HttpOnly(仅 HTTP):防止 Cookie 被 JavaScript 访问,主要用于防止 XSS 攻击。
下面我们重点讲解 Domain 和 Path 如何影响共享。
同一域名下的共享 (最常见)
这是最基本的情况,当你在一个应用中设置了一个 Cookie,它默认可以被该域名下的所有页面共享。
场景: www.example.com 下的所有页面
Java 代码示例 (使用 Servlet API):
// 在 Servlet 的 doGet 或 doPost 方法中
Cookie cookie = new Cookie("username", "john_doe");
// 设置 Cookie 的有效期,单位为秒 (7天)
cookie.setMaxAge(7 * 24 * 60 * 60);
// 设置 Cookie 的作用路径,"/" 表示在整个域名下都可用
cookie.setPath("/");
// 将 Cookie 添加到响应中
response.addCookie(cookie);
工作原理:
- 设置过程: 当用户访问
www.example.com/login时,服务器执行上述代码,通过响应头Set-Cookie: username=john_doe; Path=/; Max-Age=604800将 Cookie 发送给浏览器。 - 共享过程: 之后,当用户再访问
www.example.com/profile或www.example.com/dashboard时,浏览器会自动在请求头中带上Cookie: username=john_doe,服务器就能读取到这个 Cookie。
跨域名共享 (关键点:Domain 属性)
我们希望一个主域名下的所有子域名都能共享同一个 Cookie。a.example.com 和 b.example.com 共享一个登录状态。
场景: a.example.com 和 b.example.com 共享 Cookie
关键技巧: 在设置 Cookie 时,将 Domain 属性设置为主域名,并且主域名前面必须有一个点 。
Java 代码示例:
Cookie cookie = new Cookie("user_session", "abc123xyz");
cookie.setMaxAge(7 * 24 * 60 * 60);
cookie.setPath("/"); // 路径设置为根路径,这样所有子域名下的所有路径都能访问
// 关键步骤:设置 Domain 属性为带点的主域名
cookie.setDomain(".example.com");
response.addCookie(cookie);
工作原理:
- 设置过程: 假设在
a.example.com设置了上述 Cookie,服务器发送的响应头是Set-Cookie: user_session=abc123xyz; Path=/; Domain=.example.com; Max-Age=604800。 - 浏览器行为: 浏览器接收到这个 Cookie,并记录其作用域为
Domain=.example.com和Path=/。 - 共享过程:
- 当用户访问
a.example.com/profile时,浏览器会带上user_session。 - 当用户访问
b.example.com/dashboard时,浏览器检查b.example.com是否匹配.example.com(是的,因为b.example.com是.example.com的子域名),因此也会带上user_session。
- 当用户访问
⚠️ 重要注意事项:
- 主域名必须一致: 只有在同一个主域名下的子域名才能这样共享。
example.com和another.com是无法通过这种方式共享 Cookie 的。 - 必须有点 :
cookie.setDomain(".example.com")是正确的,如果写成cookie.setDomain("example.com"),那么该 Cookie 只会在example.com下有效,而不会在a.example.com等子域名下有效,这是一个非常容易出错的地方。 - 浏览器策略: 现代浏览器出于安全考虑,可能会对跨站 Cookie(Third-party Cookies)进行更严格的限制,但对于同一主域名下的子域名,这种共享方式仍然是标准且可靠的。
不同顶级域名之间的共享 (几乎不可能)
出于安全和隐私的考虑,浏览器严格禁止在不同顶级域名之间共享 Cookie。example.com 和 google.com 之间无法通过常规方式共享 Cookie。
为什么不可能?
这被称为“同源策略”(Same-Origin Policy)的一部分,如果允许跨顶级域名共享 Cookie,任何一个网站都可以读取另一个网站的 Cookie,这将导致严重的安全漏洞(CSRF 攻击)。
替代方案:
如果需要在两个完全不同的网站之间共享用户状态,通常采用以下替代方案:
- 单点登录:这是最标准的解决方案,使用一个专门的认证中心(如 OAuth2, SAML 协议),用户登录一次后,认证中心会颁发一个令牌,其他网站通过验证这个令牌来识别用户身份。
- 后端共享存储:将用户登录信息存储在一个共享的数据库或缓存(如 Redis)中,用户在网站 A 登录后,网站 B 可以通过查询这个共享存储来获取用户信息,但这需要两个后端系统之间有某种关联(比如共享用户ID体系)。
跨协议共享 (HTTP vs HTTPS)
Secure 属性的作用:
- 如果一个 Cookie 被标记为
Secure(通过cookie.setSecure(true)),那么它只能通过 HTTPS 连接发送,如果尝试通过 HTTP 连接访问,浏览器不会带上这个 Cookie。
场景: 网站同时提供 HTTP 和 HTTPS 访问
- 问题: 如果你在 HTTPS 页面设置了一个
SecureCookie,那么当用户切换到 HTTP 页面时,这个 Cookie 将不会被发送,导致用户状态丢失。 - 解决方案:
- 不使用
Secure属性:如果必须支持 HTTP,就不能设置Secure,但这会降低安全性。 - 强制全站 HTTPS:最佳实践是整个网站都启用 HTTPS,这样
Secure属性就能安全地使用,确保 Cookie 只在加密通道中传输。
- 不使用
跨路径共享
Path 属性的作用:
Path属性用于限定 Cookie 在域名下的哪个或哪些路径下有效。
场景: www.example.com/app 和 www.example.com/app/api
-
设置:
cookie.setPath("/app"); -
效果: 这个 Cookie 只会在请求 URL 以
/app开头的路径下被发送。www.example.com/app/home-> 会带上www.example.com/app/api/v1/user-> 会带上www.example.com/other-> 不会带上
-
实现完全共享: 如果希望 Cookie 在整个域名下所有路径都共享,必须设置为
cookie.setPath("/");。
总结与最佳实践
| 共享场景 | 关键属性 | Java 代码示例 | 备注 |
|---|---|---|---|
| 同一域名下 | Path="/" |
cookie.setPath("/"); |
最常见的情况,确保所有页面都能访问。 |
| 同一主域名的子域名间 | Domain=".example.com" 和 Path="/" |
cookie.setDomain(".example.com");cookie.setPath("/"); |
必须有点 ,是实现子域名共享的关键。 |
| 不同顶级域名间 | 无 | 不支持 | 出于安全原因,浏览器禁止此操作,应使用 SSO 或共享后端。 |
| 跨协议 (HTTP/HTTPS) | Secure 属性 |
cookie.setSecure(true); |
设置后,Cookie 只在 HTTPS 下有效,推荐全站 HTTPS。 |
| 跨路径 | Path 属性 |
cookie.setPath("/app"); |
限定 Cookie 在特定路径下生效。 |
代码中的其他重要属性:
setMaxAge(int seconds): 设置 Cookie 的存活时间。> 0: Cookie 在指定的秒数后过期。= 0: 删除 Cookie(浏览器收到后会将该 Cookie 删除)。< 0: 或不设置,表示“会话 Cookie”,浏览器关闭后即失效。
setHttpOnly(boolean flag): 设置为true可以防止 Cookie 被 JavaScript 的document.cookieAPI 访问,能有效防御 XSS 攻击。强烈推荐为存储敏感信息(如 Session ID)的 Cookie 设置此属性。
通过合理组合使用 Domain、Path、Secure 和 HttpOnly 属性,你就可以精确控制 Java Web 应用中 Cookie 的共享范围和安全性。
