本文目录导读:

设计 PHP 项目中的 Cookie 过期规则,核心是平衡安全性、用户体验和业务需求,以下是一套从基础到高级的完整设计指南。
核心概念:Cookie 的两种过期机制
- 会话 Cookie (Session Cookie):不设置 Expires 或 Max-Age 属性,浏览器关闭后自动删除。
- 持久 Cookie (Persistent Cookie):设置了
Expires或Max-Age,在指定时间后删除。
// 设置会话 Cookie (浏览器关闭即失效)
setcookie('name', 'value');
// 设置持久 Cookie (30天后失效)
setcookie('name', 'value', time() + 86400 * 30);
// 或使用 Max-Age (更推荐, 相对时间)
setcookie('name', 'value', ['expires' => time() + 86400 * 30, 'samesite' => 'Lax']);
// 注意: PHP 7.3+ 推荐使用 options 数组形式
设计原则与通用规则
- 最小必要原则:Cookie 只存标识符(如 Session ID、Token),不存敏感数据(密码、证件号)。
- 安全优先:必须设置
HttpOnly、Secure、SameSite属性。 - 区分业务场景:登录态、购物车、偏好设置、7天免登录等,过期时间应不同。
常见场景的过期规则设计
用户登录态(最核心)
-
短期会话:会话 Cookie + Session 机制(默认)。
- 优点:最安全,用户关闭浏览器即退出。
- 缺点:体验差,频繁登录。
- 代码:
session_start();(PHP 默认使用会话 Cookie)。
-
长期免登录(记住我):持久 Cookie + Token 刷新机制。
- 设计要点:
- 使用随机 Token(非用户密码)存储在 Cookie 和数据库中。
- 过期时间:建议 7-30天,一般不超过 30 天。
- 刷新规则:每次有效请求时,重新生成 Token 并更新 Cookie 和数据库,防止固定 Token 被窃取后永久有效。
- 安全处理:Cookie 中的 Token 应该被哈希后再存入数据库(不要存明文)。
- 代码示例:
- 设计要点:
// 1. 用户登录时勾选“记住我”
if ($rememberMe) {
$token = bin2hex(random_bytes(32)); // 生成随机 Token
$expires = time() + 86400 * 7; // 7天后过期
// 存储到数据库 (用户ID, 哈希后的Token, 过期时间)
$hashedToken = hash('sha256', $token);
saveTokenToDatabase($userId, $hashedToken, $expires);
// 设置 Cookie
setcookie('remember_token', $token, [
'expires' => $expires,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax'
]);
}
// 2. 用户下次访问时验证
if (!isset($_SESSION['user_id']) && isset($_COOKIE['remember_token'])) {
$token = $_COOKIE['remember_token'];
$hashedToken = hash('sha256', $token);
// 从数据库查找匹配且未过期的 Token
$userData = findTokenInDatabase($hashedToken);
if ($userData && $userData['expires'] > time()) {
// 重新登录会话
$_SESSION['user_id'] = $userData['user_id'];
// **关键: 刷新 Token** (防止固定 Token 泄露)
rotateRememberMeToken($userData['user_id']);
} else {
// Token 无效或过期, 删除 Cookie
setcookie('remember_token', '', time() - 3600);
}
}
购物车(未登录状态)
- 设计:持久 Cookie,过期时间灵活。
- 推荐时间:3-14天(避免用户在选商品过程中购物车丢失)。
- 注意:购物车数据量可能很大,Cookie 有大小限制(4KB),可以用 Session 或数据库存储,Cookie 只存一个 Session ID。
// 存储购物车数据到 Session, 浏览器关闭即消失不合适
// 方案: 使用独立的购物车 Session ID 并设置持久 Cookie
$cartSessionId = session_create_id();
$expires = time() + 86400 * 7;
setcookie('cart_session_id', $cartSessionId, $expires, '/', '', true, true);
用户偏好设置(主题、语言、字体大小)
- 设计:持久 Cookie,过期时间非常长(365天或更长)。
- 安全性:不敏感,可以
HttpOnly = false(前端 JS 可读取,用于动态换肤),但建议还是HttpOnly=true并通过 API 读取。 - 示例:
setcookie('theme', 'dark', [
'expires' => time() + 86400 * 365, // 一年
'path' => '/',
'samesite' => 'Lax'
]);
跟踪与分析(如 Google Analytics 的 _ga)
- 设计:持久 Cookie,1-2 年。
- 注意:需符合 GDPR/中国个人信息保护法,用户需同意。
高级设计:Token 轮换与吊销机制
这是防止 Cookie 被窃取后滥用(持久登录令牌)的关键。
- 轮换机制:
- 每次使用“记住我” Token 成功验证后,立即生成新 Token(旧 Token 失效)。
- 这样即使黑客窃取了某个 Token,用户下次正常登录后,旧 Token 自动失效。
- 版本化:
- 数据库 Token 记录增加
version字段,每次轮换版本号 +1,服务器只认最新版本号的 Token。
- 数据库 Token 记录增加
- 吊销机制:
- 用户修改密码、注销其他设备、账户被锁定等操作时,删除/作废该用户所有遗忘 Token。
- 需要数据库支持:
DELETE FROM user_tokens WHERE user_id = ?。
过期时间的安全考量
- 敏感操作:支付、修改密码、绑定手机等操作不能只靠 Cookie 登录态,必须再次验证密码或 2FA。
- 会话超时:
- 空闲超时:用户长时间无操作(如 30 分钟),自动销毁 Session(短 Token)。
- 绝对超时:用户从登录开始,最多会话 8 小时或 24 小时,强制重新登录(适用于银行、后台管理系统)。
- 实现:在 Session 中存储
last_activity和login_time,每次请求时检查。
// 会话空闲超时
if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > 1800)) {
session_destroy();
session_start();
// 重定向到登录页
}
$_SESSION['last_activity'] = time();
// 会话绝对超时
if (isset($_SESSION['login_time']) && (time() - $_SESSION['login_time'] > 28800)) { // 8小时
// 强制注销
}
完整的设置示例(现代 PHP 7.3+)
// 设置一个安全的长久登录 Cookie
$cookieName = 'auth_token';
$cookieValue = bin2hex(random_bytes(32));
$expires = time() + 86400 * 14; // 14 天后过期
setcookie($cookieName, $cookieValue, [
'expires' => $expires,
'path' => '/',
'domain' => 'example.com', // 匹配你的域名
'secure' => true, // 仅 HTTPS
'httponly' => true, // 禁止 JavaScript 访问
'samesite' => 'Lax' // 防止 CSRF, Lax 是较好的平衡
]);
// 删除 Cookie
setcookie($cookieName, '', [
'expires' => time() - 3600,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax'
]);
最佳实践一览表
| 场景 | 类型 | 过期时间 | 安全属性 | 备注 |
|---|---|---|---|---|
| 登录会话 | Session | 浏览器关闭 | HttpOnly, Secure, SameSite |
默认行为,最安全 |
| 记住我 | Persistent | 7-30 天 | HttpOnly, Secure, SameSite,Token 轮换 |
必须结合数据库 Token 存储和轮换 |
| 购物车 | Persistent | 3-14 天 | HttpOnly, Secure |
最好用 Session ID 控制,数据存服务端 |
| 偏好设置 | Persistent | 1 年 | Secure, SameSite (可 HttpOnly=false 给前端使用) |
安全性低,可灵活处理 |
| 分析跟踪 | Persistent | 1-2 年 | Secure, SameSite |
需用户同意 |
| 敏感操作令牌 | 一次性 | 5-15 分钟 | HttpOnly, Secure, SameSite=Strict |
用于支付、密码重置确认等,用完立即删除 |
| CSRF Token | Session | 浏览器关闭 | SameSite=Strict |
放在表单隐藏字段,不通过 Cookie |
最后建议:不要完全依赖 Cookie 过期时间来保证安全,配合服务端 Session 管理、IP 变化检测、异常登录行为报警等,构建多层防御体系。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播