防止下载HTML5video(右键单击保存)?

如何从浏览器的右键菜单中禁用“保存video为…”以防止客户端下载video?

是否有更完整的解决scheme阻止客户端直接访问文件path?

事实上, 你不能 。 但是你可以让下载更加困难


浏览器让抓取太简单了

因为这是浏览器devise的目的:提供内容 – 这意味着将内容提供给用户 。 为了向您展示这是多么容易,下面是我通常几乎在任何videostream站点上抓取video:

准备您的首选浏览器debugging器的networking选项卡,并让video加载。 然后在加载的资源中查找它。 video通常以.flv或.mp4格式播放,而.mp3格式的audio格式。 当你发现url时,打开一个新的标签页/窗口并打开链接。 浏览器将下载文件。


让它更难

以下是使抓取者的生活更艰苦的方法。 就像我刚才所说的那样,这些都不是防呆的方法,但至less可以避开打滑。

video到canvas技术

最近在研究JS中的运动检测时,我从HTML5Doctor中看到了这篇文章 。 这涉及到通过一个<video> ,然后与一些JSstream式video,从字面上复制video到<canvas> 。 这里有一个例子 ,其中video是在前面,而在后面的canvas得到了来自同一video的数据。

基本上,你所做的是:

  • 预先定义HTML或dynamic地将一个<canvas>插入到DOM中。 这是用户看到的“玩家”。
  • 通过JSdynamic创build一个video标签,附加到隐藏的DOM,并给它一个stream的URL。 这将是canvas的video源。
  • 然后使用JS,您定期从刚刚创build的<video>获取数据,并将其绘制到<canvas> 。 通过这一步,video被传送到canvas。

这是整个例程的基础。 由于您的播放器现在隐藏了canvas和真实video,因此您可以尝试右键单击所有您想要的并保存。 由于canvas的行为与页面上的图像相似,因此只能保存canvas上显示的框架的一个镜头。 至于控件, JS有一个用于控制<video>的API,所以你可以创build自定义的button和滑块。

但是,如果他们知道你正在这样做,他们会发现你的隐藏的video元素,你拧了。 这导致我们接下来的方法,补充了这个前端技术,在服务器端的援助。

临时资源url

有一件事你可以做,以防止这种方法是防止链接可重用 。 使链接一次性,临时,一次性使用。 一旦玩家使用一次性url加载,将其丢弃。 使其无法使用。

与CSRF预防类似,当浏览器请求带有video的页面时,让它生成一个随机标记并将其存储在服务器端的某个存储中供以后参考。 同时, 将其附加到您的video的url ,如下所示:

 //we load some video with id 1234324 from your site using this url //and the token generated on page load is appended as sid http://yoursite.com/media.php?video_id=1234324&sid=a0s9d8a98a0d98asd09809wq0e9 

现在,当你的播放器加载video时,它将使用这个带有令牌的URL。 让服务器validation令牌。

如果是好的,则将videostream传输并从服务器销毁令牌以避免重复使用。 这基本上使url“一次使用”。 如果使用无效标记,则返回适当的标题作为响应 ,如403或许。

要添加更多的安全性,通过将标记与时间戳一起存储来强制URL的到期。 然后比较请求时间戳和存储的时间戳,如果它仍在“使用窗口”内。 使这个“使用窗口”足够短,以供玩家在页面上使用,但不足以让滑动抓取该URL并将其粘贴到另一个选项卡/窗口/下载器中。

对于那些希望简单地从html5video中删除右击“保存”选项的人来说,这是一个简单的解决scheme

 $(document).ready(function(){ $('#videoElementID').bind('contextmenu',function() { return false; }); }); 

简单的答案,

你不能

如果他们正在看你的video,他们已经有了

你可以放慢他们,但不能阻止他们。

我通常使用的最好的方法是非常简单的,我完全禁用整个页面的上下文菜单,纯html + javascript:

  <body oncontextmenu="return false;"> 

而已! 我这样做,因为你总是可以通过右键单击来查看源代码。
好吧,你说:“我可以直接使用浏览器视图源”,这是真的,但我们从你不能停止下载html5video的事实开始。

是的,你可以通过三个步骤来做到这一点:


  1. 将要保护的文件放在运行代码的目录的子目录中。

    http://www.foo.com/player.html
    http://www.foo.com/videos/video.mp4

  2. 将文件保存在名为“.htaccess”的子目录中,并添加下面的行。

    http://www.foo.com/videos/.htaccess

     #Contents of .htaccess RewriteEngine on RewriteCond %{HTTP_REFERER} !^http://foo.com/.*$ [NC] RewriteCond %{HTTP_REFERER} !^http://www.foo.com/.*$ [NC] RewriteRule .(mp4|mp3|avi)$ - [F] 

现在源代码链接是无用的 ,但我们仍然需要确保任何试图下载文件的用户都不能直接提供给文件。

  1. 获得更完整的解决scheme ,现在使用Flash播放器(或HTMLcanvas)提供video,而不要直接链接到video。 要删除右键菜单,添加到您的HTML:

     <body oncontextmenu="return false;"> 

结果:

http://www.foo.com/player.html 将正确播放video ,但如果您访问www.foo.com/videos/video.mp4:

错误代码403:FORBIDDEN

这将工作直接下载,curl,盗链,你的名字。

对于这两个问题,这是一个完整的答案,而不是对这个问题的回答:“我可以阻止用户下载他们已经下载的video。”

PHP将html5video标签与会话密钥是随机string一起发送,值是文件名。

 ini_set('session.use_cookies',1); session_start(); $ogv=uniqid(); $_SESSION[$ogv]='myVideo.ogv'; $webm=uniqid(); $_SESSION[$webm]='myVideo.webm'; echo '<video autoplay="autoplay">' .'<source src="video.php?video='.$ogv.' type="video/ogg">' .'<source src="video.php?video='.$webm.' type="video/webm">' .'</video>'; 

现在PHP被要求发送video。 PHP恢复文件名; 删除会话并立即发送video。 另外,所有的'no cache'和mime-type头文件都必须存在。

 ini_set('session.use_cookies',1); session_start(); $file='myhiddenvideos/'.$_SESSION[$_GET['video']]; $_SESSION=array(); $params = session_get_cookie_params(); setcookie(session_name(),'', time()-42000,$params["path"],$params["domain"], $params["secure"], $params["httponly"]); if(!file_exists($file) or $file==='' or !is_readable($file)){ header('HTTP/1.1 404 File not found',true); exit; } readfile($file); exit: 

现在,如果用户在一个新标签中复制url或使用上下文菜单,他将没有运气。

至less可以阻止非技术人员使用右键单击上下文菜单下载video。 您可以使用oncontextmenu属性禁用任何元素的上下文菜单。

 oncontextmenu="return false;" 

这适用于body元素(整个页面),或仅在video标签中使用它的单个video。

 <video oncontextmenu="return false;" controls>...</video> 

您可以

作为一个客户端开发人员,我build议使用blob url,bolb url是一个引用二进制对象的客户端端url

 <video id="id" width="320" height="240" type='video/mp4' controls > </video> 

在html中留下您的videosrc空白,并在js使用ajax获取video文件,确保响应types是blob

 window.onload = function() { var xhr = new XMLHttpRequest(); xhr.open('GET', 'mov_bbb.mp4', true); xhr.responseType = 'blob'; //important xhr.onload = function(e) { if (this.status == 200) { console.log("loaded"); var blob = this.response; var video = document.getElementById('id'); video.oncanplaythrough = function() { console.log("Can play through video without stopping"); URL.revokeObjectURL(this.src); }; video.src = URL.createObjectURL(blob); video.load(); } }; xhr.send(); } 

+1简单和跨浏览器的方式:你也可以把透明的图片放在video上,用css z-index和opacity。 因此用户将在上下文菜单中看到“保存图片为”而不是“保存video”。

使用Vimeo等服务:loginVimeo > Goto Video > Settings > Privacy > Mark as Secured ,并selectembedded域。 一旦embedded域被设置,它将不允许任何人embeddedvideo或从浏览器显示它,除非从指定的域连接。 所以,如果你的服务器上有一个安全的页面,加载了iframe中的Vimeo播放器,这使得很难避开。

我们最终使用了AWS CloudFront和过期的URL。 该video将加载,但到用户右键单击并select保存时,他们最初收到的videourl已过期。 searchCloudFront Origin Access Identity。

生成videourl需要一个可以在AWS CLI中创build的密钥对。 仅供参考这不是我的代码,但它工作的很好!

 $resource = 'http://cdn.yourwebsite.com/videos/yourvideourl.mp4'; $timeout = 4; //This comes from key pair you generated for cloudfront $keyPairId = "AKAJSDHFKASWERASDF"; $expires = time() + $timeout; //Time out in seconds $json = '{"Statement":[{"Resource":"'.$resource.'","Condition" {"DateLessThan":{"AWS:EpochTime":'.$expires.'}}}]}'; //Read Cloudfront Private Key Pair $fp=fopen("/absolute/path/to/your/cloudfront_privatekey.pem","r"); $priv_key=fread($fp,8192); fclose($fp); //Create the private key $key = openssl_get_privatekey($priv_key); if(!$key) { echo "<p>Failed to load private key!</p>"; return; } //Sign the policy with the private key if(!openssl_sign($json, $signed_policy, $key, OPENSSL_ALGO_SHA1)) { echo '<p>Failed to sign policy: '.openssl_error_string().'</p>'; return; } //Create url safe signed policy $base64_signed_policy = base64_encode($signed_policy); $signature = str_replace(array('+','=','/'), array('-','_','~'), $base64_signed_policy); //Construct the URL $url = $resource.'?Expires='.$expires.'&Signature='.$signature.'&Key-Pair-Id='.$keyPairId; return '<div class="videowrapper" ><video autoplay controls style="width:100%!important;height:auto!important;"><source src="'.$url.'" type="video/mp4">Your browser does not support the video tag.</video></div>'; 

@ Clayton-Graul有我正在寻找的东西,除了我需要使用AngularJS的网站的CoffeeScript版本。 以防万一你也需要这个,下面是你在AngularJS控制器中的问题:

  # This is how to we do JQuery ready() dom stuff $ -> # let's hide those annoying download video options. # of course anyone who knows how can still download # the video, but hey... more power to 'em. $('#my-video').bind 'contextmenu', -> false 

“奇怪的事情正在圈k”(这是真的)

至less会禁用右键单击菜单。

将此添加到头标记中

 <script> window.oncontextmenu = function() { return false; } </script> 

看起来像通过websocket传输video是一个可行的select,如在stream中的帧和画在canvas上的东西。

通过使用JavaScript的websockets进行videostream式传输

我认为这将提供另一个级别的保护,使客户更难以获得video,当然,解决您的问题与“保存video为…”右键单击上下文菜单选项(矫枉过正?!)。