本文目录导读:

在PHP项目中实现分享链接过期时间,常见有这几种方式:
在URL中嵌入过期时间戳
<?php
// 生成分享链接
function generateShareLink($fileId, $expireHours = 24) {
$expireTime = time() + ($expireHours * 3600);
$token = md5($fileId . $expireTime . 'your-secret-key');
$link = "http://yourdomain.com/share.php?id={$fileId}&expire={$expireTime}&token={$token}";
return $link;
}
// 验证分享链接
function validateShareLink($fileId, $expireTime, $token) {
// 1. 检查是否过期
if (time() > $expireTime) {
return ['valid' => false, 'message' => '链接已过期'];
}
// 2. 验证token
$expectedToken = md5($fileId . $expireTime . 'your-secret-key');
if ($token !== $expectedToken) {
return ['valid' => false, 'message' => '无效的链接'];
}
return ['valid' => true, 'message' => '链接有效'];
}
// 使用示例
$link = generateShareLink('file_123', 48); // 48小时过期
echo "分享链接:<a href='{$link}'>{$link}</a>";
?>
使用数据库存储和管理
<?php
// 数据库表结构
// CREATE TABLE share_links (
// id INT PRIMARY KEY AUTO_INCREMENT,
// file_id VARCHAR(100),
// token VARCHAR(64) UNIQUE,
// created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
// expires_at TIMESTAMP,
// is_active BOOLEAN DEFAULT TRUE,
// access_count INT DEFAULT 0,
// max_access INT DEFAULT NULL
// );
// 生成分享链接
function createShareLink($fileId, $expireHours = 24, $maxAccess = null) {
$db = new PDO('mysql:host=localhost;dbname=yourdb', 'user', 'pass');
$token = bin2hex(random_bytes(32)); // 生成随机token
$expiresAt = date('Y-m-d H:i:s', strtotime("+{$expireHours} hours"));
$stmt = $db->prepare("INSERT INTO share_links (file_id, token, expires_at, max_access) VALUES (?, ?, ?, ?)");
$stmt->execute([$fileId, $token, $expiresAt, $maxAccess]);
return "http://yourdomain.com/share/{$token}";
}
// 验证并访问分享链接
function accessShareLink($token) {
$db = new PDO('mysql:host=localhost;dbname=yourdb', 'user', 'pass');
$stmt = $db->prepare("SELECT * FROM share_links WHERE token = ? AND is_active = TRUE");
$stmt->execute([$token]);
$link = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$link) {
return ['valid' => false, 'message' => '链接不存在'];
}
// 检查过期时间
if (strtotime($link['expires_at']) < time()) {
// 自动标记为过期
$db->prepare("UPDATE share_links SET is_active = FALSE WHERE id = ?")->execute([$link['id']]);
return ['valid' => false, 'message' => '链接已过期'];
}
// 检查访问次数限制
if ($link['max_access'] !== null && $link['access_count'] >= $link['max_access']) {
return ['valid' => false, 'message' => '已达到访问次数限制'];
}
// 更新访问计数
$db->prepare("UPDATE share_links SET access_count = access_count + 1 WHERE id = ?")->execute([$link['id']]);
return [
'valid' => true,
'file_id' => $link['file_id'],
'access_count' => $link['access_count'] + 1
];
}
?>
使用Redis实现(高性能方案)
<?php
class RedisShareLink {
private $redis;
private $prefix = 'share_link:';
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
// 生成分享链接
public function createLink($fileId, $ttl = 86400) { // ttl: 过期时间(秒),默认24小时
$token = bin2hex(random_bytes(16));
$key = $this->prefix . $token;
// 存储文件ID,设置过期时间
$this->redis->setex($key, $ttl, $fileId);
return "http://yourdomain.com/share/{$token}";
}
// 获取文件
public function getFile($token) {
$key = $this->prefix . $token;
$fileId = $this->redis->get($key);
if ($fileId === false) {
return ['valid' => false, 'message' => '链接已过期或无效'];
}
// 可选:限制访问次数
$accessKey = $key . ':access';
$accessCount = $this->redis->incr($accessKey);
// 如果设置最大访问次数
if ($accessCount > 5) { // 最多访问5次
$this->redis->del($key); // 删除链接
return ['valid' => false, 'message' => '已达到访问次数限制'];
}
// 设置访问计数过期时间(与主key相同)
$this->redis->expire($accessKey, $this->redis->ttl($key));
return ['valid' => true, 'file_id' => $fileId];
}
// 手动删除链接
public function revokeLink($token) {
$key = $this->prefix . $token;
return $this->redis->del($key);
}
}
// 使用示例
$share = new RedisShareLink();
// 创建48小时过期的链接
$link = $share->createLink('file_456', 172800);
echo "分享链接:{$link}";
// 验证链接
$result = $share->getFile('token123');
if ($result['valid']) {
echo "文件ID:" . $result['file_id'];
} else {
echo "错误:" . $result['message'];
}
?>
分享链接控制器示例
<?php
// share_controller.php
class ShareController {
// 生成分享链接
public function createShareLink($request) {
$fileId = $request['file_id'];
$expireType = $request['expire_type'] ?? '24h'; // 7d, 30d, forever
$expireMap = [
'1h' => 3600,
'24h' => 86400,
'7d' => 604800,
'30d' => 2592000,
'forever' => null
];
$ttl = $expireMap[$expireType] ?? 86400;
// 生成链接
if ($ttl === null) {
// 永久链接,不过期
$link = $this->generatePermanentLink($fileId);
} else {
$link = $this->generateExpiringLink($fileId, $ttl);
}
return [
'success' => true,
'link' => $link,
'expires_in' => $ttl,
'created_at' => date('Y-m-d H:i:s')
];
}
// 前端页面显示
public function sharePage() {
?>
<!DOCTYPE html>
<html>
<head>
<title>分享文件</title>
</head>
<body>
<form method="POST" action="/api/share">
<input type="hidden" name="file_id" value="123">
<label>过期时间:</label>
<select name="expire_type">
<option value="1h">1小时</option>
<option value="24h" selected>24小时</option>
<option value="7d">7天</option>
<option value="30d">30天</option>
<option value="forever">永久</option>
</select>
<button type="submit">生成分享链接</button>
</form>
</body>
</html>
<?php
}
}
?>
推荐方案选择
- 小型项目:使用URL嵌入时间戳方式,简单直接
- 中型项目:使用数据库方案,管理更灵活
- 高性能需求:使用Redis方案,速度快,支持自动过期
- 安全性要求高:结合数据库+加密token,记录访问日志
安全建议
- 使用HTTPS传输
- token长度至少32位,使用随机生成
- 重要文件限制访问次数
- 记录访问日志便于审计
- 定期清理已过期的链接记录