如何禁用浏览器右键菜单中的“另存为...”选项,以防止客户下载视频?
是否有更完整的解决方案可以防止客户直接访问文件路径?
如何禁用浏览器右键菜单中的“另存为...”选项,以防止客户下载视频?
是否有更完整的解决方案可以防止客户直接访问文件路径?
这是因为浏览器的设计初衷就是为了提供内容。但你可以通过一些方式使得下载更加困难。
我只需将视频上传到第三方视频网站,如YouTube或Vimeo。它们拥有良好的视频管理工具,优化播放设备,并努力防止视频被轻松地复制,您无需做任何努力。
你可以禁用contextmenu
事件,也就是“右键单击”。这将防止普通的网络小偷通过右键单击和“另存为”来盗取你的视频。但是他们仍然可以禁用JS并绕过此限制,或通过浏览器调试器找到视频源。此外,这会导致用户体验不佳。上下文菜单中有很多合法的选项,而不仅仅是“另存为”。
使用自定义视频播放器库。它们中的大多数实现了视频播放器,可以自定义上下文菜单以满足您的需求,因此您不会看到默认的浏览器上下文菜单。如果它们提供了类似于“另存为”的菜单项,您也可以禁用它。但是,这仍然是一个JS解决方法。其弱点与解决方法1类似。
另一种方法是使用HTTP直播流来提供视频。它的基本原理是将视频分成块并逐个传输。这就是大多数流媒体网站提供视频的方式。因此,即使您设法保存,您也只能保存一个块,而不是整个视频。需要更多努力使用一些专业软件收集所有块并将它们拼接起来。
另一种技术是在<canvas>
上绘制 <video>
。通过一些JavaScript代码,页面上的<canvas>
元素渲染来自隐藏的<video>
的帧。由于它是一个<canvas>
元素,上下文菜单将使用<img>
的菜单,而不是<video>
的菜单。您将获得“保存图像”而不是“保存视频”。
您还可以利用CSRF令牌。您的服务器会在页面上发送一个令牌。然后使用该令牌获取视频。在提供视频或获取HTTP 401之前,您的服务器会检查它是否为有效令牌。这个想法是,只有从页面访问才能获得令牌,才能获取视频,而不能直接访问视频URL。
<video>
的“src”一起发送。当您的页面加载完成时,数据库和页面都有了该令牌。一旦<video>
开始加载(访问端点),服务器会检查令牌是否在数据库中,删除它并流式传输文件。如果由于第二次访问而导致令牌不在那里,则不要流式传输文件。 - Joseph这是一个简单的解决方案,适用于希望从html5视频中简单地删除右键"保存"选项的人。
$(document).ready(function(){
$('#videoElementID').bind('contextmenu',function() { return false; });
});
www.foo.com/player.html
www.foo.com/videos/video.mp4
在该子目录中保存一个名为“.htaccess”的文件,并添加下面的行。
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]
现在源链接已经无用了,但我们仍需要确保任何试图下载文件的用户无法直接获取文件。
对于更完整的解决方案,现在使用Flash播放器(或HTML画布)来提供视频,并且永远不要直接链接到视频。如果只是想删除鼠标右键菜单,请将以下代码添加到您的HTML中:
<body oncontextmenu="return false;">
www.foo.com/player.html将正确播放视频,但如果您访问www.foo.com/videos/video.mp4:
错误代码403:被禁止的访问
这是对两个问题的完整回答,而不是回答“我能阻止用户下载他们已经下载过的视频”的问题。
.htaccess
文件中有一个反引号,应该将其删除。 - MAZux简单的回答:
如果他们正在观看你的视频,那么他们已经拥有它了
你可以减慢他们,但无法阻止他们。
作为客户端开发人员,我建议使用Blob URL, Blob URL是客户端URL,指的是二进制对象。
<video id="id" width="320" height="240" type='video/mp4' controls > </video>
在HTML中,将视频的src
属性留空,在JS中使用AJAX获取视频文件,确保响应类型为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();
}
注意:不建议使用此方法来处理大文件。
编辑
使用跨域阻止和头部令牌检查来防止直接下载。
如果视频是通过API传递的,则使用不同的HTTP方法(PUT / POST)而不是“GET”。
我通常使用的最好方式非常简单,就是在整个页面中完全禁用上下文菜单,纯html+javascript:
<body oncontextmenu="return false;">
就这样!我这么做是因为你总是可以通过右键单击查看源代码。
html5
视频。PHP发送带有会话的html5视频标签,其中键是随机字符串,值是文件名。
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被要求发送视频。PHP恢复文件名;删除会话并立即发送视频。此外,所有“不缓存”和MIME类型头都必须存在。
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:
<video src="..." ... controlsList="nodownload">
https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElement/controlsList
虽然它不能防止视频被保存,但它确实会移除下载按钮和右键菜单中的“另存为”选项。
我们可以通过隐藏右键菜单来增加难度,像这样:
<video oncontextmenu="return false;" controls>
<source src="https://yoursite.com/yourvideo.mp4" >
</video>
$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>';
文件→另存为
)保存它。即使您可以某种方式阻止此操作,他们也可以使用 view-source 找到文件的 URL。即使您可能会对其进行一些模糊处理,他们也可以从缓存中获取。即使您可能会将其复杂化(例如流式传输),他们也可以使用嗅探器或其他工具来捕获网络流量。事实是,如果您将其发送给用户,他们可以保存它。没有任何绕开这一点的方法。您需要问自己的问题是,为什么您非常需要阻止它?这真的很必要吗?这是否值得花费时间和让用户感到不友好? - Synetech