简介
通过3种方法(nginx/php/nginx+php)来对视频点播VOD做权限控制。
Github项目地址
部署
✅  需要安装 Git, Docker, Docker-compose
1 2 3 4 5 6
   |  $ git clone https://github.com/copriwolf/vod-authority-control-demo.git $ cd vod-authority-control-demo 
 
  $ docker-compose up
 
  | 
 
测试
- 添加hosts 
127.0.0.1 local.video-demo.com 
- 浏览器地址
http://local.video-demo.com 
- 有3种鉴定方法可以选择(php/nginx/php+nginx)
 
- 如果你想正常播放,追加 
?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 {              			             local args, err = ngx.req.get_uri_args()
                           local token = args.token             local key = args.key
              if key == nil or token == nil              then                 ngx.exit(ngx.HTTP_FORBIDDEN)             end
                           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 {                          local verify_url = "/nginx-auth-with-php/verify/"
                           res = ngx.location.capture(verify_url, { args = ngx.req.get_uri_args()})
                           if res.status ~= 200 or res.body ~= "ok"             then                 ngx.exit(ngx.HTTP_FORBIDDEN)             end
                           ngx.exec("@ok")         }     }
  | 
 
同时,我们把验证代码放在PHP中,可以更为灵活的修改验证算法。(不再需要改一次就要在终端运行nginx -s reload来让配置生效)
1 2 3 4 5 6 7 8 9 10 11 12
   | <?php  function verify($args) {          if ($args['token']) {         return 'ok';     } }
  $check = verify($_REQUEST) ? 'ok' : 'failed'; echo $check; exit;
   | 
 
            使用该方法,
好处:使用Nginx控制权限入口,PHP做具体鉴权逻辑,分离了职责后更为灵活,部署后修改验证算法更简单容易;
坏处:需要同时配置好Nginx以及PHP的环境与联动。