本文目录导读:

我来介绍几种PHP视频防盗链的实现方法:
基于Referer验证
<?php
class VideoAntiHotlink {
// 允许的域名列表
private $allowedDomains = [
'www.yourdomain.com',
'yourdomain.com',
'cdn.yourdomain.com'
];
// 检查Referer
public function checkReferer() {
if (!isset($_SERVER['HTTP_REFERER'])) {
// 直接访问,拒绝
$this->blockAccess();
return false;
}
$referer = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
// 检查是否在允许列表中
foreach ($this->allowedDomains as $domain) {
if (strpos($referer, $domain) !== false) {
return true;
}
}
// 不符合条件,拒绝访问
$this->blockAccess();
return false;
}
// 阻止访问
private function blockAccess() {
header('HTTP/1.0 403 Forbidden');
header('Content-Type: application/json');
$response = [
'status' => 'error',
'message' => 'Access denied'
];
echo json_encode($response);
exit;
}
}
?>
Token验证机制
<?php
class TokenAntiHotlink {
private $secretKey = 'your-secret-key-here';
private $tokenExpire = 3600; // Token有效期(秒)
// 生成访问令牌
public function generateToken($videoId, $userId = '') {
$timestamp = time();
$data = [
'video_id' => $videoId,
'user_id' => $userId,
'timestamp' => $timestamp,
'expire' => $timestamp + $this->tokenExpire
];
$token = base64_encode(json_encode($data));
$signature = $this->generateSignature($token);
return [
'token' => $token,
'signature' => $signature,
'expire_time' => $data['expire']
];
}
// 验证访问令牌
public function validateToken($token, $signature) {
// 验证签名
if (!$this->verifySignature($token, $signature)) {
return ['valid' => false, 'message' => 'Invalid signature'];
}
// 解码token
$data = json_decode(base64_decode($token), true);
// 检查是否过期
if (time() > $data['expire']) {
return ['valid' => false, 'message' => 'Token expired'];
}
return ['valid' => true, 'data' => $data];
}
// 生成签名
private function generateSignature($token) {
return md5($token . $this->secretKey);
}
// 验证签名
private function verifySignature($token, $signature) {
return $this->generateSignature($token) === $signature;
}
// 获取视频流
public function serveVideo($videoPath, $token, $signature) {
$result = $this->validateToken($token, $signature);
if (!$result['valid']) {
header('HTTP/1.0 403 Forbidden');
echo json_encode($result);
exit;
}
// 检查视频文件是否存在
if (!file_exists($videoPath)) {
header('HTTP/1.0 404 Not Found');
echo json_encode(['status' => 'error', 'message' => 'Video not found']);
exit;
}
// 设置适当的响应头
header('Content-Type: video/mp4');
header('Content-Length: ' . filesize($videoPath));
header('Content-Disposition: inline; filename="' . basename($videoPath) . '"');
header('Accept-Ranges: bytes');
header('Cache-Control: no-cache, must-revalidate');
// 输出视频内容
readfile($videoPath);
exit;
}
}
?>
时间戳防盗链
<?php
class TimestampAntiHotlink {
private $privateKey = 'your-private-key';
private $expireTime = 1800; // 30分钟
// 生成带时间戳的URL
public function generateUrl($videoUrl) {
$timestamp = time() + $this->expireTime;
$hash = md5($videoUrl . $timestamp . $this->privateKey);
$params = [
't' => $timestamp,
'h' => $hash
];
$separator = (strpos($videoUrl, '?') === false) ? '?' : '&';
return $videoUrl . $separator . http_build_query($params);
}
// 验证时间戳URL
public function validateUrl() {
$timestamp = isset($_GET['t']) ? $_GET['t'] : 0;
$hash = isset($_GET['h']) ? $_GET['h'] : '';
// 检查是否过期
if ($timestamp < time()) {
return ['valid' => false, 'message' => 'Link expired'];
}
// 验证哈希值
$currentUrl = $this->getCurrentUrl();
$expectedHash = md5($currentUrl . $timestamp . $this->privateKey);
if ($hash !== $expectedHash) {
return ['valid' => false, 'message' => 'Invalid hash'];
}
return ['valid' => true];
}
// 获取当前URL(不含参数)
private function getCurrentUrl() {
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://';
$host = $_SERVER['HTTP_HOST'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
return $protocol . $host . $path;
}
}
?>
完整示例 - 视频播放器防盗链
<?php
// video_player.php - 视频播放页面
session_start();
require_once 'AntiHotlink.php';
$videoId = isset($_GET['video_id']) ? $_GET['video_id'] : 0;
$tokenHandler = new TokenAntiHotlink();
// 生成视频访问令牌
$tokenData = $tokenHandler->generateToken($videoId, $_SESSION['user_id'] ?? 'guest');
?>
<!DOCTYPE html>
<html>
<head>Video Player</title>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>
<body>
<video id="videoPlayer" controls width="800">
<source id="source" type="video/mp4">
</video>
<script>
const videoPlayer = document.getElementById('videoPlayer');
const source = document.getElementById('source');
// 生成带token的视频URL
const videoUrl = `serve_video.php?video_id=<?php echo $videoId; ?>&token=<?php echo urlencode($tokenData['token']); ?>&signature=<?php echo $tokenData['signature']; ?>`;
// 检查是否支持HLS
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(videoUrl);
hls.attachMedia(videoPlayer);
} else if (videoPlayer.canPlayType('application/vnd.apple.mpegurl')) {
videoPlayer.src = videoUrl;
} else {
source.src = videoUrl;
videoPlayer.load();
}
</script>
</body>
</html>
<?php
// serve_video.php - 视频服务脚本
require_once 'AntiHotlink.php';
$tokenHandler = new TokenAntiHotlink();
$videoId = isset($_GET['video_id']) ? $_GET['video_id'] : 0;
$token = isset($_GET['token']) ? $_GET['token'] : '';
$signature = isset($_GET['signature']) ? $_GET['signature'] : '';
// 获取视频实际路径
$videoPath = getVideoPath($videoId); // 自定义函数
// 验证并服务视频
$tokenHandler->serveVideo($videoPath, $token, $signature);
?>
Nginx配合使用
# nginx.conf 配置
location /videos/ {
# 防盗链配置
valid_referers none blocked www.yourdomain.com yourdomain.com;
if ($invalid_referer) {
return 403;
}
# 限制访问方法
limit_except GET {
deny all;
}
# 缓存配置
expires 7d;
add_header Cache-Control "public, no-transform";
}
数据库存储验证
<?php
class DatabaseAntiHotlink {
private $db;
public function __construct($db) {
$this->db = $db;
}
// 记录视频访问日志
public function logAccess($videoId, $userId, $ip) {
$stmt = $this->db->prepare("
INSERT INTO video_access_logs
(video_id, user_id, ip_address, access_time)
VALUES (?, ?, ?, NOW())
");
return $stmt->execute([$videoId, $userId, $ip]);
}
// 检查访问频率限制
public function checkRateLimit($ip, $limit = 100, $period = 3600) {
$stmt = $this->db->prepare("
SELECT COUNT(*) as count
FROM video_access_logs
WHERE ip_address = ?
AND access_time > DATE_SUB(NOW(), INTERVAL ? SECOND)
");
$stmt->execute([$ip, $period]);
$result = $stmt->fetch();
return $result['count'] < $limit;
}
// 用户权限验证
public function checkUserPermission($userId, $videoId) {
$stmt = $this->db->prepare("
SELECT id FROM user_permissions
WHERE user_id = ?
AND (video_id = ? OR video_id IS NULL)
AND expire_time > NOW()
");
$stmt->execute([$userId, $videoId]);
return $stmt->fetch() !== false;
}
}
?>
使用建议:
- 多层防护:组合使用多种防盗链机制
- 定期更新:定期更换密钥和配置
- 日志监控:记录异常访问行为
- 性能优化:使用CDN配合防盗链
- 兼容性:考虑各种浏览器和播放器
这些方法可以有效防止视频资源被盗链,建议根据实际需求选择适合的方案。