php实现记住我
PHP 实现记住我功能
实现记住我功能通常涉及生成持久化的登录令牌(如 Cookie),并在用户下次访问时自动验证。以下是具体实现方法:
生成并存储登录令牌
用户登录时生成唯一令牌,存储到数据库和客户端 Cookie:
// 用户登录成功后
if ($remember_me) {
$token = bin2hex(random_bytes(32)); // 生成随机令牌
$expiry = time() + 60 * 60 * 24 * 30; // 30天后过期
// 存储到数据库(示例使用PDO)
$stmt = $pdo->prepare("INSERT INTO remember_tokens (user_id, token, expires) VALUES (?, ?, ?)");
$stmt->execute([$user_id, hash('sha256', $token), date('Y-m-d H:i:s', $expiry)]);
setcookie('remember_token', $token, $expiry, '/', '', true, true); // 安全设置
}
验证记住我令牌
每次页面加载时检查是否存在有效令牌:
if (!isset($_SESSION['user_id']) && isset($_COOKIE['remember_token'])) {
$token = $_COOKIE['remember_token'];
$hashed_token = hash('sha256', $token);
// 查询数据库
$stmt = $pdo->prepare("SELECT user_id, expires FROM remember_tokens WHERE token = ? AND expires > NOW()");
$stmt->execute([$hashed_token]);
$row = $stmt->fetch();
if ($row) {
$_SESSION['user_id'] = $row['user_id']; // 重新登录用户
// 可选:更新令牌延长有效期(见下方)
}
}
安全增强措施
令牌轮换
每次验证后生成新令牌,防止固定令牌被窃取:
// 验证成功后
$new_token = bin2hex(random_bytes(32));
$new_expiry = time() + 60 * 60 * 24 * 30;
// 更新数据库
$pdo->prepare("UPDATE remember_tokens SET token = ?, expires = ? WHERE token = ?")
->execute([hash('sha256', $new_token), date('Y-m-d H:i:s', $new_expiry), $hashed_token]);
// 设置新Cookie
setcookie('remember_token', $new_token, $new_expiry, '/', '', true, true);
清理过期令牌
定期清理数据库中的过期令牌:
$pdo->exec("DELETE FROM remember_tokens WHERE expires < NOW()");
用户登出处理
用户主动登出时删除令牌:
// 删除数据库令牌
if (isset($_COOKIE['remember_token'])) {
$hashed_token = hash('sha256', $_COOKIE['remember_token']);
$pdo->prepare("DELETE FROM remember_tokens WHERE token = ?")->execute([$hashed_token]);
// 删除Cookie
setcookie('remember_token', '', time() - 3600, '/');
}
注意事项
-
HTTPS 必需
确保网站启用 HTTPS,防止 Cookie 被中间人窃取。 -
SameSite 属性
设置 Cookie 时建议添加 SameSite 属性:setcookie('remember_token', $token, [ 'expires' => $expiry, 'path' => '/', 'secure' => true, 'httponly' => true, 'samesite' => 'Strict' ]); -
令牌熵值
使用random_bytes()或openssl_random_pseudo_bytes()确保令牌足够随机。
通过以上方法可实现安全可靠的记住我功能,兼顾用户体验与账户安全。







