视频点播权限控制-方法与示例

简介

通过3种方法(nginx/php/nginx+php)来对视频点播VOD做权限控制。
Github项目地址

部署

✅ 需要安装 Git, Docker, Docker-compose

1
2
3
4
5
6
# git project
$ git clone https://github.com/copriwolf/vod-authority-control-demo.git
$ cd vod-authority-control-demo

# deploy
$ docker-compose up

测试

  1. 添加hosts 127.0.0.1 local.video-demo.com
  2. 浏览器地址http://local.video-demo.com
  3. 有3种鉴定方法可以选择(php/nginx/php+nginx)
  4. 如果你想正常播放,追加 ?token=anyWordYouWant到url尾部,形如 local.video-demo.com/php-auth/?token=XXX

核心实现

Nginx方法

使用了nginx-mod-http-lua模块,使用了lua语言在nginx的配置文件中对视频文件进行了权限校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
location ~ .*\.(mp4|flv|avi)$ {
content_by_lua_block {
-- # DEMO
-- get args 获取参数
local args, err = ngx.req.get_uri_args()

-- check args 检查参数
local token = args.token
local key = args.key

if key == nil or token == nil
then
ngx.exit(ngx.HTTP_FORBIDDEN)
end

-- comparison 将获取的key进行md5加密后与token比较
if token ~= ngx.md5(key)
then
ngx.exit(ngx.HTTP_FORBIDDEN)
end

return ngx.exec("@ok")
}
}

location @ok {
default_type 'video/mp4';
}

使用该方法,
好处:部署非常快,不需要额外的php支持;
坏处:开发调试比较麻烦,每次改完conf文件都需要$ nginx -s reload,对于没有nginx操作权限的开发比较苦恼。


PHP方法

直接在代码内编写一个校验函数逻辑

1
2
3
4
5
6
7
8
9
function checkAuth()
{
$token = $_GET['token'];
if (!$token) {
echo 'token is null';
exit;
}
}
checkAuth();

通过后再进行视频协议的转发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function GetMp4File($file)
{
$size = filesize($file);
header("Content-type: video/mp4");
header("Accept-Ranges: bytes");
if (isset($_SERVER['HTTP_RANGE'])) {
header("HTTP/1.1 206 Partial Content");
list($name, $range) = explode("=", $_SERVER['HTTP_RANGE']);
list($begin, $end) =explode("-", $range);
if ($end == 0) {
$end = $size - 1;
}
} else {
$begin = 0;
$end = $size - 1;
}
header("Content-Length: " . ($end - $begin + 1));
header("Content-Disposition: filename=".basename($file));
header("Content-Range: bytes ".$begin."-".$end."/".$size);
$fp = fopen($file, 'rb');
fseek($fp, $begin);
while (!feof($fp)) {
$p = min(1024, $end - $begin + 1);
$begin += $p;
echo fread($fp, $p);
}
fclose($fp);
}
GetMp4File("../demo.mp4");

使用该方法,
好处:php代码简单易用,而且不需要特意配置nginx配置;
坏处:由于每次请求都是php去读取视频文件,会导致请求瞬间占用大量CPU,内存。


Nginx+PHP方法

我们把逻辑验证代码写在PHP,但是让Nginx来控制资源的读取,有利于降低CPU与内存的消耗。

首先我们会在Nginx通过nginx-mod-http-lua模块来转发token和key到PHP处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
location @nginx_verify_with_php {
content_by_lua_block {
-- set Verify URL
local verify_url = "/nginx-auth-with-php/verify/"

-- request verify API
res = ngx.location.capture(verify_url, { args = ngx.req.get_uri_args()})

-- check verification
if res.status ~= 200 or res.body ~= "ok"
then
ngx.exit(ngx.HTTP_FORBIDDEN)
end

-- return the resource
ngx.exec("@ok")
}
}

同时,我们把验证代码放在PHP中,可以更为灵活的修改验证算法。(不再需要改一次就要在终端运行nginx -s reload来让配置生效)

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
function verify($args)
{
// verify code
if ($args['token']) {
return 'ok';
}
}

$check = verify($_REQUEST) ? 'ok' : 'failed';
echo $check;
exit;

使用该方法,
好处:使用Nginx控制权限入口,PHP做具体鉴权逻辑,分离了职责后更为灵活,部署后修改验证算法更简单容易;
坏处:需要同时配置好Nginx以及PHP的环境与联动。