本文目录导读:

在PHP项目中实现用户自定义过期时间,常见有以下几种方案,我按推荐程度排序介绍:
基于数据库字段(最常用)
实现方式
// 用户表增加过期字段
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100),
expire_at DATETIME, -- 过期时间
is_active TINYINT DEFAULT 1
);
// 创建用户时设置过期时间
function createUserWithExpire($username, $email, $expireDays = 30) {
$expireAt = date('Y-m-d H:i:s', strtotime("+{$expireDays} days"));
$sql = "INSERT INTO users (username, email, expire_at)
VALUES (?, ?, ?)";
// 使用PDO或mysqli执行
}
// 验证用户是否过期
function checkUserExpired($userId) {
$sql = "SELECT expire_at FROM users WHERE id = ?";
$user = $db->fetchOne($sql, [$userId]);
if (!$user) return true;
return strtotime($user['expire_at']) < time();
}
// 每次请求时检查
function authMiddleware() {
if (checkUserExpired($_SESSION['user_id'])) {
// 用户已过期,跳转到过期页面或禁止访问
header('Location: /expired.php');
exit;
}
}
使用Session + 数据库(临时过期更灵活)
// 登录时设置session过期
session_start();
function loginWithCustomExpire($userId, $expireMinutes = 30) {
// 数据库记录
$sql = "UPDATE users SET session_expire_at = ? WHERE id = ?";
$expireAt = date('Y-m-d H:i:s', time() + $expireMinutes * 60);
// Session设置
$_SESSION['user_id'] = $userId;
$_SESSION['expire_at'] = $expireAt;
$_SESSION['login_time'] = time();
}
// 中间件检查
function checkSessionExpired() {
if (!isset($_SESSION['expire_at'])) {
return false;
}
if (strtotime($_SESSION['expire_at']) < time()) {
// 过期,销毁session
session_destroy();
return true;
}
// 可选:每次访问更新过期时间(滑动过期)
$slidingExpire = true;
if ($slidingExpire) {
$_SESSION['expire_at'] = date('Y-m-d H:i:s',
time() + 30 * 60); // 再延长30分钟
}
return false;
}
基于JWT Token(适合API接口)
// 使用 firebase/php-jwt 库
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class CustomJWT {
private $secretKey;
public function __construct($secretKey) {
$this->secretKey = $secretKey;
}
// 生成带自定义过期时间的Token
public function generateToken($userId, $expireHours = 24) {
$payload = [
'iss' => 'your-app', // 签发者
'iat' => time(), // 签发时间
'exp' => time() + $expireHours * 3600, // 过期时间
'user_id' => $userId,
'custom_data' => [
'role' => 'premium',
'max_requests' => 1000
]
];
return JWT::encode($payload, $this->secretKey, 'HS256');
}
// 验证Token
public function validateToken($token) {
try {
$decoded = JWT::decode($token, new Key($this->secretKey, 'HS256'));
// 检查自定义过期条件
if ($decoded->custom_data->max_requests < 0) {
return false; // 请求次数用完也算过期
}
return (array)$decoded;
} catch (\Exception $e) {
// Token过期或无效
return false;
}
}
}
// 使用示例
$jwt = new CustomJWT('your-secret-key-here');
$token = $jwt->generateToken(123, 48); // 48小时过期
Redis缓存实现(高性能场景)
class RedisExpireManager {
private $redis;
public function __construct($redis) {
$this->redis = $redis;
}
// 设置用户自定义过期
public function setUserExpire($userId, $ttlSeconds) {
$key = "user:{$userId}:expire";
// 存储过期时间戳
$this->redis->setex($key, $ttlSeconds, time() + $ttlSeconds);
// 也可以构建用户会话
$sessionKey = "user:{$userId}:session";
$sessionData = json_encode([
'user_id' => $userId,
'expire_at' => time() + $ttlSeconds,
'last_activity' => time()
]);
$this->redis->setex($sessionKey, $ttlSeconds, $sessionData);
}
// 检查是否过期
public function isExpired($userId) {
$key = "user:{$userId}:expire";
$expireAt = $this->redis->get($key);
if (!$expireAt) return true; // 不存在视为过期
return $expireAt < time();
}
// 更新过期时间(滑动窗口)
public function refreshExpire($userId, $additionalSeconds = 3600) {
$key = "user:{$userId}:expire";
if ($this->redis->exists($key)) {
// 重新设置过期时间
$this->redis->expire($key, $additionalSeconds);
}
}
}
完整项目集成示例
<?php
// UserAuth.php - 用户认证类
class UserAuth {
private $db;
private $expireStrategies = [];
public function __construct($db) {
$this->db = $db;
}
// 注册过期策略
public function addExpireStrategy($name, callable $checker) {
$this->expireStrategies[$name] = $checker;
}
// 用户登录
public function login($username, $password, $expireConfig = []) {
// 验证用户...
// 设置过期
$expireConfig = array_merge([
'type' => 'fixed', // fixed, sliding, hybrid
'duration' => 3600, // 1小时
'max_idle' => 1800 // 最大空闲时间
], $expireConfig);
// 存储过期配置
$_SESSION['expire_config'] = $expireConfig;
$_SESSION['login_time'] = time();
$_SESSION['last_activity'] = time();
$_SESSION['user_id'] = $userId;
return true;
}
// 检查过期
public function checkExpired() {
if (!isset($_SESSION['expire_config'])) {
return false;
}
$config = $_SESSION['expire_config'];
$now = time();
switch ($config['type']) {
case 'fixed':
// 固定过期时间
return ($_SESSION['login_time'] + $config['duration']) < $now;
case 'sliding':
// 滑动过期:基于最后活动时间
$isExpired = ($_SESSION['last_activity'] + $config['duration']) < $now;
if (!$isExpired) {
$_SESSION['last_activity'] = $now; // 更新活动时间
}
return $isExpired;
case 'hybrid':
// 混合模式:总时长+空闲超时
$totalExpired = ($_SESSION['login_time'] + $config['duration']) < $now;
$idleExpired = ($_SESSION['last_activity'] + $config['max_idle']) < $now;
if (!$idleExpired) {
$_SESSION['last_activity'] = $now;
}
return $totalExpired || $idleExpired;
}
return false;
}
// 用户自定义过期查询
public function getUserCustomExpire($userId) {
// 从数据库获取用户的个性化过期设置
$sql = "SELECT expire_type, expire_value, expire_unit
FROM user_expire_config
WHERE user_id = ?";
$config = $this->db->fetchOne($sql, [$userId]);
if (!$config) {
// 默认过期设置
return [
'type' => 'fixed',
'value' => 24,
'unit' => 'hours'
];
}
// 根据配置计算过期时间
switch ($config['unit']) {
case 'minutes':
$expireSeconds = $config['expire_value'] * 60;
break;
case 'hours':
$expireSeconds = $config['expire_value'] * 3600;
break;
case 'days':
$expireSeconds = $config['expire_value'] * 86400;
break;
case 'custom':
// 自定义逻辑
$expireSeconds = $this->calculateCustomExpire($config);
break;
}
return [
'type' => $config['expire_type'],
'duration' => $expireSeconds
];
}
private function calculateCustomExpire($config) {
// 复杂的自定义过期逻辑
// 周末不过期、特定时间段过期等
$now = new DateTime();
$weekDay = $now->format('N');
if ($weekDay >= 6) { // 周末
return 86400 * 2; // 2天
}
return 3600; // 工作日1小时
}
}
// 使用示例
$auth = new UserAuth($db);
// 注册自定义过期检查策略
$auth->addExpireStrategy('weekend_free', function($userId) {
$now = new DateTime();
return $now->format('N') < 6; // 非周末返回false(不过期)
});
$auth->addExpireStrategy('usage_limit', function($userId) {
// 检查API调用次数
return getApiUsage($userId) > 1000;
});
// 用户登录时设置自定义过期
$expireConfig = $auth->getUserCustomExpire($userId);
$auth->login($username, $password, $expireConfig);
推荐方案选择
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 简单网站 | 数据库字段 | 实现简单,易于维护 |
| REST API | JWT Token | 无状态,适合分布式 |
| 高并发 | Redis | 性能好,支持过期通知 |
| 复杂权限 | 数据库+自定义策略 | 灵活可扩展 |
选择哪种方案取决于你的项目规模、并发量和业务复杂度,对于大多数中小型项目,数据库字段方案就足够了。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播