本文目录导读:

- 核心权限模型设计
- 基础权限检查中间件
- 播放链接保护(核心安全措施)
- 视频防盗链(Referer / User-Agent 验证)
- 流媒体服务器级别的保护(生产环境推荐)
- 完整的前后端交互示例
- 安全最佳实践
- 性能优化建议
在PHP项目中实现点播视频的权限管控播放,通常需要结合用户认证、资源授权和播放链接保护三个层面,以下是几种常见的实现方案,从简单到复杂逐步说明:
核心权限模型设计
首先建立基本的用户-角色-资源模型:
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50),
role ENUM('admin', 'vip', 'normal', 'free'),
expire_time DATETIME -- VIP 到期时间
);
-- 视频资源表
CREATE TABLE videos (
id INT PRIMARY KEY,VARCHAR(200),
file_path VARCHAR(500),
category VARCHAR(50),
price DECIMAL(10,2), -- 单点价格
is_free BOOLEAN DEFAULT false
);
-- 用户购买记录表
CREATE TABLE user_video_access (
id INT PRIMARY KEY,
user_id INT,
video_id INT,
purchase_time DATETIME,
expire_time DATETIME,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (video_id) REFERENCES videos(id)
);
基础权限检查中间件
// video_permission.php
function checkVideoPermission($userId, $videoId) {
// 1. 获取视频信息
$video = getVideoById($videoId);
// 2. 如果是免费视频,直接放行
if ($video['is_free']) {
return true;
}
// 3. 获取用户信息
$user = getUserById($userId);
// 4. 检查 VIP 权限
if ($user['role'] == 'vip' || $user['role'] == 'admin') {
// 检查 VIP 是否过期
if ($user['expire_time'] > date('Y-m-d H:i:s')) {
return true;
}
}
// 5. 检查单次购买权限
$access = getUserVideoAccess($userId, $videoId);
if ($access && $access['expire_time'] > date('Y-m-d H:i:s')) {
return true;
}
// 6. 检查用户等级是否满足视频等级要求
if (checkUserLevel($user['role'], $video['required_level'])) {
return true;
}
return false;
}
播放链接保护(核心安全措施)
直接暴露视频路径非常危险,需要使用动态签名URL:
方案A:简单 Token 验证
// 生成播放链接
function generateVideoUrl($videoId, $userId, $expireTime = 3600) {
$secretKey = 'your-secret-key-123'; // 服务端密钥
$timestamp = time() + $expireTime;
// 生成签名
$sign = md5($videoId . $userId . $timestamp . $secretKey);
// 构建播放地址
return "/play.php?v=" . $videoId .
"&t=" . $timestamp .
"&s=" . $sign .
"&u=" . $userId;
}
// 播放页面验证
// play.php
if (!validateVideoToken($_GET)) {
die('Access Denied');
}
function validateVideoToken($params) {
$secretKey = 'your-secret-key-123';
$videoId = $params['v'];
$userId = $params['u'];
$timestamp = $params['t'];
$sign = $params['s'];
// 验证时间是否过期
if ($timestamp < time()) {
return false;
}
// 验证签名是否匹配
$expectedSign = md5($videoId . $userId . $timestamp . $secretKey);
return $sign === $expectedSign;
}
方案B:使用 Nginx Secure Link(推荐)
在 Nginx 配置中启用 secure_link:
location /videos/ {
# 开启 secure_link
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr secret_key";
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
# 视频文件位置
alias /data/videos/;
mp4;
mp4_buffer_size 4M;
mp4_max_buffer_size 10M;
}
PHP 生成安全链接:
function generateSecureLink($videoPath) {
$secretKey = 'your-nginx-secret';
$expires = time() + 3600; // 1小时有效
// 生成 MD5 值
$md5 = base64_encode(md5($expires . $videoPath . $_SERVER['REMOTE_ADDR'] . $secretKey, true));
$md5 = strtr($md5, '+/', '-_');
$md5 = str_replace('=', '', $md5);
return "/videos" . $videoPath . "?md5=" . $md5 . "&expires=" . $expires;
}
视频防盗链(Referer / User-Agent 验证)
// 检查来源
function checkReferer() {
$allowedDomains = ['yourdomain.com', '*.yourdomain.com'];
$referer = $_SERVER['HTTP_REFERER'] ?? '';
foreach ($allowedDomains as $domain) {
if (strpos($referer, $domain) !== false) {
return true;
}
}
return false;
}
流媒体服务器级别的保护(生产环境推荐)
对于大规模点播,建议使用专业的流媒体服务器:
FFmpeg + Nginx RTMP 模块
application vod {
# 使用 HLS 协议
hls on;
hls_path /tmp/hls;
# 播放权限验证
on_play http://your-server.com/auth.php;
on_publish http://your-server.com/auth.php;
}
auth.php 验证脚本:
<?php
// 从请求中获取用户和视频信息
$userId = $_GET['user_id'] ?? '';
$videoId = $_GET['video_id'] ?? '';
$token = $_GET['token'] ?? '';
// 验证权限
if (checkVideoAccess($userId, $videoId, $token)) {
header('HTTP/1.0 200 OK');
echo 'Authorized';
} else {
header('HTTP/1.0 403 Forbidden');
echo 'Forbidden';
}
完整的前后端交互示例
// 前端请求播放
// JavaScript
function requestPlayVideo(videoId) {
fetch('/api/get-video-url', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
video_id: videoId,
user_token: localStorage.getItem('token')
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 使用 player.js 播放
const player = new Player({
url: data.play_url, // 带签名的临时链接
token: data.play_token
});
player.play();
} else {
alert('没有播放权限');
}
});
}
// 后端生成播放URL
// /api/get-video-url.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$userId = validateUserToken($_POST['user_token']);
$videoId = $_POST['video_id'];
if (checkVideoPermission($userId, $videoId)) {
// 生成1小时有效的临时链接
$playUrl = generateTemporaryUrl($videoId, $userId, 3600);
echo json_encode([
'success' => true,
'play_url' => $playUrl,
'expires_in' => 3600
]);
} else {
http_response_code(403);
echo json_encode(['success' => false, 'message' => '无权限']);
}
}
安全最佳实践
- 使用临时链接:播放链接设置有效期(建议 1-4 小时)
- 单次验证:同一个链接不能多次使用
- 限制 IP:签名中包含用户 IP,防止链接盗用
- 水印技术:在视频中动态添加用户水印
- 加密存储:视频文件存储时加密,播放时解密
- CDN 防护:使用 CDN 的 Referer 防盗链和 IP 黑白名单
- 日志审计:记录所有播放请求,便于追溯
性能优化建议
- 缓存权限:使用 Redis 缓存权限检查结果
- 异步验证:大规模场景使用消息队列异步处理权限验证
- CDN 边缘计算:在 CDN 边缘节点进行权限验证
推荐的生产环境方案组合:
- 用户认证:JWT Token
- 权限检查:RBAC + 购买记录
- 播放保护:Nginx Secure Link + 时间戳签名
- 防盗链:Referer + User-Agent 检查
- 流媒体:HLS/MPEG-DASH + DRM(商业内容)
根据你的项目规模和安全要求,可以选择合适的方案组合,对于商业级内容,建议考虑专业的 DRM 解决方案(如 Widevine、PlayReady)和 CDN 防盗链服务。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播