浏览器在发起 HTTP 请求时,会根据以下条件决定是否携带特定的 Cookie:
1. 同源判断(同源策略下的自动携带)
Cookie 只会自动携带到满足 请求的 URL 与 Cookie 的:
- 协议(Protocol):若 Cookie 设置了
Secure
属性,则仅通过 HTTPS 发送。 - 域名(Domain):Cookie 的
Domain
范围内。 - 端口(Port):若存在则必须匹配设置的端口。
- 路径(Path):URL 路径需符合设置的
Path
范围(如/api
则匹配/api/articles
)。
2. 实际携带规则
只有当以下所有条件满足时,Cookie 才会被自动携带:
- 请求的域名在 Cookie 的 Domain 范围内;
- 请求的路径在 Cookie 的 Path 范围内;
- 请求使用了 HTTP 或 HTTPS(取决于 Secure 属性);
- 遵循 SameSite 属性的配置。
Cookie 的域名由服务器设定
当用户通过浏览器访问服务器(例如 https://api.example.com
)时,服务器可以通过 Set-Cookie
响应头发送 Cookie。Cookie 的域名由服务器在 Set-Cookie
头中指定,具体规则如下:
默认情况(未显式设置 Domain
):
- 如果服务器 未设置
Domain
属性,Cookie 的Domain
默认为 服务器响应的域名。- 例如:若服务器响应的域名为
api.example.com
,则 Cookie 的Domain
为api.example.com
。
- 例如:若服务器响应的域名为
显式设置 Domain
:
- 服务器可以通过
Domain=xxx
显式指定 Cookie 的作用域。- 例如:
Domain=example.com
→ 该 Cookie 可被example.com
及其所有子域名(如api.example.com
,web.example.com
)访问。
- 例如:
关键属性对自动携带的影响
1. Domain
属性
- 作用:指定哪些域名可以接收该 Cookie。
- 示例:
- 设置:
Domain=example.com
→ 匹配example.com
、sub.example.com
(如果Domain
设置为.example.com
)的请求会携带 Cookie。 - 未设置:默认为当前域名(如网站部署在
auth.example.com
,则请求必须在同一子域名下才携带)。
- 设置:
2. Path
属性
- 作用:指定 Cookie 对应的路径范围。
- 示例:
Path=/api
→ 只有请求路径以/api
开头时携带(如/api/articles
,/api/users
)。
- 示例:
3. Secure
属性
- 作用:Cookie 仅通过 HTTPS 协议发送。
- 示例:若设置
Secure
,且请求使用http://
→ 禁止发送。
4. SameSite
属性
- 作用:控制 Cookie 是否随跨站请求发送。
SameSite=Strict
:仅允许同源请求携带,跨站请求(如链接跳转或表单提交)不携带。SameSite=Lax
:对安全的请求方式(如 GET)且跨站的“顶级导航”(如点击链接)携带,但 POST 请求不携带。SameSite=None
:允许跨站请求携带,但必须同时设置Secure
属性。
前端获取 Cookie 的限制
前端通过 document.cookie
读取 Cookie 时,只能访问 与当前页面同源的 Cookie(遵循同源策略)。
同源要求必须满足以下三个条件:
- 协议(HTTP/HTTPS)一致;
- 域名一致;
- 端口一致。
示例场景:
假设:
- 前端应用域名为
frontend.example.com
; - 后端服务器域名为
api.example.com
; - Cookie 由后端服务器设置,且
Domain
未显式指定(缺省为api.example.com
)。
此时:
- 前端应用(frontend.example.com)无法直接读取
api.example.com
的 Cookie(跨域不可见)。
因为同源策略禁止跨不同域名的 Cookie 访问。
实现前端与后端 Cookie 共享的方案
方案1:统一基础域名
- 部署结构:
- 前端应用和后端 API 共用同一基础域名,如:
- 前端:
https://app.example.com
- 后端:
https://api.example.com
- 前端:
- 服务器设置
Domain=.example.com
。
- 前端应用和后端 API 共用同一基础域名,如:
- 效果:
前后端同属.example.com
域名下,Cookie 可共享。
方案2:通过代理服务器(CORS 配合)
- 前端通过代理请求 Cookie:
- 前端请求自己的域服务器(如
frontend.example.com
),服务器作为代理向后端(api.example.com
)获取 Cookie,并返回给前端。 - 需要配置 CORS 和跨域的 Cookie 策略。
-
实现原理与步骤
1. 架构图示
- 前端请求自己的域服务器(如
用户浏览器(frontend.example.com) → 前端代理服务器(frontend.example.com/api) → 后端 API(api.example.com)
2. 关键流程
-
前端发起请求:
- 用户页面在
frontend.example.com
中发起 AJAX 请求到代理接口(如/api/data
),并携带withCredentials: true
(允许发送跨域 Cookie)。
- 用户页面在
fetch('https://frontend.example.com/api/data', {
method: 'GET',
credentials: 'include' // 允许携带 Cookie
});
代理服务器转发请求:
- 代理服务器(例如 Node.js、Nginx 或反向代理工具)接收到请求后,会将路径重写(如
/api/data
→https://api.example.com/data
),并转发请求到后端。 - 要求代理服务器必须设置为 带 Cookie 的转发,例如:
// Node.js (Express) 代理示例:
app.use('/api', expressProxy({
target: 'https://api.example.com',
changeOrigin: true,
pathRewrite: { '^/api': '' },
cookieDomainRewrite: 'api.example.com', // 重写 Cookie 的 Domain
headers: {
origin: 'frontend.example.com' // 防止请求头 Origin 被篡改
},
onProxyReq: (proxyReq) => {
if (proxyReq.getHeader('Cookie')) {
// 展示原始请求的 Cookie(调试用途)
console.log('Forwarding Cookies:', proxyReq.getHeader('Cookie'));
}
}
}));
后端响应和 Cookie 的返回:
- 后端
api.example.com
返回资源时,设置响应头Set-Cookie
发送 Cookie: -
Access-Control-Allow-Origin 为请求的源
,而不是通配符 *,因为 * 不允许携带 cookie。 - Cookie 的
SameSite
属性未设置为Strict
或Lax
。若需跨站携带,需设置为SameSite=None; Secure
(仅限 HTTPS) -
HTTP/1.1 200 OK Content-Type: application/json Set-Cookie: sessionId=abc123; Domain=api.example.com; Path=/; HttpOnly; Secure; SameSite=None Access-Control-Allow-Origin: https://frontend.example.com Access-Control-Allow-Credentials: true
-
浏览器存储 Cookie:
- 浏览器检测到
Access-Control-Allow-Origin
和Access-Control-Allow-Credentials
存在,允许 Cookie 跨域存储(前提是域名、端口、协议匹配)。 sessionId=abc123
被存储到api.example.com
的 Cookie 储存中。
- 浏览器检测到
方案3:直接在前端域设置 Cookie
- 如果 Cookie 是由前端自己生成或需要与前端同域
// 在 frontend.example.com 页面中,通过 JavaScript 设置 Cookie
document.cookie = "theme=dark; path=/; domain=frontend.example.com";
常见误区澄清
-
误区:前端的域名决定 Cookie 的 Domain。
纠正:Cookie 的 Domain 由服务器在Set-Cookie
头中显式设置,或默认为响应的域名。 -
误区:前端可以直接读取任何服务器的 Cookie。
纠正:严格遵循同源策略,跨域 Cookie 不可见。 -
误解场景:
若前端在web.example.com
,后端在api.example.com
,且未设置Domain=...
,此时 Cookie的 Domain 是api.example.com
,前端无法直接访问。安全最佳实践
- 最小化 Cookie 作用域:
- 仅共享必需的子域名,避免
Domain=.
全局匹配。
- 仅共享必需的子域名,避免
- 启用安全属性:
Secure
(HTTPS 必须);HttpOnly
(防 XSS);SameSite
(防 CSRF)。
- 敏感数据不要存入 Token:
- 推荐使用短期有效的 Token(如 15 分钟),配合 Refresh Token 机制。