定义:
简单来说cookie就是一段 key-value 形式的文本片段,通讯时服务器可通过 http header 下发 cookie 信息记录到用户浏览器;浏览器在后续通讯时会自动带上。
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2023 12:00:00 UTC; path=/";
cookie的作用
http 本身是一种无状态协议,服务器无法单纯从网络协议层面判定用户身份,因此需要通过 cookie 方式持久化用户凭证,让服务器能映射回用户信息。
,主要用于实现记录用户登录状态、浏览器行为跟踪。
cookie的使用
- 在 is 中写入;后续浏览器会自动帮我们带上
// 设置cookie
function setCookie(name, value) {
document.cookie = `${name}=${value};path=/`;
}
// 获取cookie
function getCookie(name) {
let cookies = document.cookie.split('; ');
for (let i = 0; i < cookies.length; i++) {
let cookiePair = cookies[i].split('=');
if (name == cookiePair[0]) {
return cookiePair[1];
}
}
return null;
}
// 使用示例
setCookie('name', 'John'); // 设置一个名为 'name' 的 cookie,值为 'John'
console.log(getCookie('name')); // 获取并输出 'name' 的 cookie 值
- 可通过服务器 response 的 set-cookie 头下发
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=John; Expires=Wed, 09 Jun 2021 10:18:14 GMT
cookie的安全性
Set-Cookie: id=a3fWa; Max-Age=2592000; Path=/; Domain=somecompany.co.uk; Secure; HttpOnly; SameSite=Lax; Expires=Wed, 21 Oct 2015 07:28:00 GMT
Max-age
:cookie 有效期
expires
:cookie 过期时间,但需注意:若同时设置 Expires
和 Max-Age
,浏览器优先采用 Max-Age
path
:cookie 生效路径,(当前:http://ww.baidu.com;path: /foo/bar),可被域下所有路径访问,若需限制作用范围(如仅 /api),需更精确设置。
secure
:仅允许通过 HTTPS 传输 Cookie,防止明文传输被截获。
HttpOnly
:禁止 JavaScript 访问 Cookie(即无法通过docuemnt.cookie获取cookie),降低 XSS 攻击窃取风险。
domain
:指定 cookie 可以送达的域名,也就是这个 cookie 能在哪些地方用;默认为当前页面所在域名;可有效防止 csrf,有一个细节,xxx.com
为严格域名;.xxx.com
为宽松域名,对子域名也能生效,但 fetch
时需要带上credentials":"include
samesite
:允许部分跨域请求携带 Cookie(如导航跳转),平衡安全性与功能性,可用于防御 csrf 攻击,属性值有:
- strict:仅同源请求发送 cookie,但过于严格,通常不太会用(例如,当前网页有一个 GitHub 链接,用e户点击跳转就不会带有GitHub 的 Cookie,跳转过去总是末登陆状态。)
- lax:稍微宽松,也限定为仅同源请求发送 cookie,但链接跳转的 get 请求除外
- none:不作限制,但要求同时设置Secure
使用 Cookie 存储用户登录状态
- 用户打开网页后,服务端生成随机、唯一会话标识符(session id),通常还会设置超时时间。
- 用户登录后,服务端记录 session id 到 user 的关联关系(内存、redis、持久化数据库等)
- 用户再次发送请求后,服务端通过 session id 找到对应 user 信息,从而实现 session 到 user 的映射
- 所以,理想方案下 cookie 并不记录用户(这也是一个安全问题),而是记录当前会话
优点:
- 应用简单,几乎不需要额外配置
- 非常标准,几乎所有服务端框架都支持
问题:
- 应尽可能减少 cookie 的使用,应用会带来网络负担
- 仅在浏览器可用,app 等场景下使用 http 时不生效
- 服务端需要记录 cookie 到用户信息的映射,压力大
- 分布式服务器场景下,需要在多服务器间共享用户态,对服务端压力较大大小有限制
最佳实践:
- 不要在cookie 存储敏感信息
- 强制启动 secure;建议启动 HttpOnly
其他存储用户登录状态方案
1. Session 方案
实现步骤:
(1) 用户登录后,服务端创建 Session 记录并返回 Session ID
(2) 客户端通过 Cookie 或 URL 参数携带 Session ID
(3)服务端根据 ID 查询 Session 数据验证身份
优点:
- 服务端完全控制会话状态,安全性高
- 支持强制注销和会话续期
缺点:
- 服务端存储压力大,需依赖 Redis 等缓存优化
- 不适用于分布式系统(需额外同步机制)
2. Token 方案(JWT)
实现步骤:
(1)服务端生成含用户 ID 和有效期的 Token,通过签名防篡改
// 生成 Token
const token = jwt.sign({ userId: 123 }, 'secret-key', { expiresIn: '1h' });
(2)客户端存储 Token 于 localStorage 或 Cookie,请求时通过 Header 发送
(3)服务端解密 Token 并验证有效性
优点:
- 无状态设计,天然支持分布式架构
- 可包含扩展字段(如权限角色)
缺点:
- Token 泄露后无法主动失效(需结合黑名单机制)
- 需自行实现自动续期逻辑
3. 本地存储方案
实现步骤:
(1) 登录成功后,将 Token 或用户数据存入浏览器存储:
// 持久化存储
localStorage.setItem('user', JSON.stringify({ name: 'Alice', token: 'xxx' }));
// 会话级存储
sessionStorage.setItem('tempData', 'value');
(2)前端路由拦截校验存储数据
优点:
- 完全由前端控制,灵活性高
- 支持复杂数据结构(如 JSON 对象)
缺点:
- 易受 XSS 攻击窃取数据(需配合 CSP 策略)
- 浏览器隐私模式可能导致存储失效