PHP项目点播视频如何权限管控播放

wen PHP项目 25

本文目录导读:

PHP项目点播视频如何权限管控播放

  1. 核心权限模型设计
  2. 基础权限检查中间件
  3. 播放链接保护(核心安全措施)
  4. 视频防盗链(Referer / User-Agent 验证)
  5. 流媒体服务器级别的保护(生产环境推荐)
  6. 完整的前后端交互示例
  7. 安全最佳实践
  8. 性能优化建议

在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. 使用临时链接:播放链接设置有效期(建议 1-4 小时)
  2. 单次验证:同一个链接不能多次使用
  3. 限制 IP:签名中包含用户 IP,防止链接盗用
  4. 水印技术:在视频中动态添加用户水印
  5. 加密存储:视频文件存储时加密,播放时解密
  6. CDN 防护:使用 CDN 的 Referer 防盗链和 IP 黑白名单
  7. 日志审计:记录所有播放请求,便于追溯

性能优化建议

  • 缓存权限:使用 Redis 缓存权限检查结果
  • 异步验证:大规模场景使用消息队列异步处理权限验证
  • CDN 边缘计算:在 CDN 边缘节点进行权限验证

推荐的生产环境方案组合:

  1. 用户认证:JWT Token
  2. 权限检查:RBAC + 购买记录
  3. 播放保护:Nginx Secure Link + 时间戳签名
  4. 防盗链:Referer + User-Agent 检查
  5. 流媒体:HLS/MPEG-DASH + DRM(商业内容)

根据你的项目规模和安全要求,可以选择合适的方案组合,对于商业级内容,建议考虑专业的 DRM 解决方案(如 Widevine、PlayReady)和 CDN 防盗链服务。

抱歉,评论功能暂时关闭!