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

是否有更完整的解决方案来阻止客户端直接访问文件路径?


当前回答

@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圈发生”(这是真的)

其他回答

你不能百分百保护它,但你可以让它更难。我解释的这些方法,是我在PluralSight和BestDotNetTraining中学习保护方法时遇到的。尽管如此,这些方法都没有阻止我下载我想要的东西,但我很难策划下载者通过他们的保护。

除了其他提到的方法禁用上下文菜单。用户仍然可以使用第三方工具,如InternetDownload manager或其他类似软件下载视频。我在这里解释的保护方法是缓解这些第三方软件。

所有这些方法的要求是,当您确定有人正在下载您的视频时,阻止用户。这样,在你禁止他们访问你的网站之前,他们只能下载一到两个视频。

免责声明

如果有人滥用这些方法或用它来伤害其他人或我举的例子中的网站,我将不承担任何责任。它只是用来分享知识,帮助你保护你的知识产品。

生成带有过期的链接

这样做的要求是为每个用户创建一个下载链接。azure blob存储或amazon s3可以很容易地处理这个问题。您可以使用视频长度到期时间戳的两倍创建下载链接。然后,您需要捕获该视频链接和请求的时间。这是下一个方法所必需的。这种方法的问题在于,当用户单击播放按钮时,将生成下载链接。

在播放按钮事件中,您将向服务器发送一个请求,并获得链接并更新源代码。

限制视频请求速率

然后监视用户请求第二个视频的速度。如果用户请求下载链接的速度太快,那么你会立即阻止他们。你不能把这个阈值设得太大,因为你可能会错误地阻止那些只是浏览或浏览视频的用户。

启用HTTP范围

use some js library like videojs to play your video, also you need to return an AcceptRange in your header. Azure blob storage supports this out of the box. this way the browser starts to download the video chunk by chunk. usually, 32byte by 32byte. then you need to listen to videojs timeupdate change and update your server about the percentage that the video is watched. the percentage that the video is watched can't be more than the percentage that video is delivered. and if you are delivering a video content without receiving any percentage change, then you can block the user. because for sure they are downloading.

实现这个很棘手,因为用户可以向前或向后跳过视频,所以在实现这个时要注意这一点。

这是BestDotnetTraining处理时间更新的方式

myPlayer.ready(function () {
    //var player = this;
    this.src({
        type: "video/mp4",
        src: videoURL
    });
    if (videoId) {
        myPlayer.play();
        this.on('timeupdate', function () {
            var currentPercent = parseInt(100 * myPlayer.currentTime() / myPlayer.duration());//calcualte as percentage
            if (currentPercent % 5 == 0) {
                //send percentage to server 
                SaveVideoDurationWatched(currentPercent, videoId);
            }
        });
    }

});

anyway, the user is able to work around this by using some download method that downloads a file through streaming. almost c# do it out of the box and for nodejs, you can use request module. then you need to start a stopWatch, listen to a package received and compare the total byte received compare to the total size. this way you can calculate a percentage and the time spent to get that amount of percentage. then use the Thread.Sleep() or something like that to delay the thread the amount that you have to wait if you watch the video normally. also before the sleep the user can call the server and update the percentage that is received. so the server thinks that the user is actually watching a video.

例如,如果你计算出到目前为止你收到了1%,那么你可以计算出你应该等待休眠下载线程的数量。通过这种方式,你下载视频的速度不会超过它的实际长度。如果一个视频是24分钟,那么下载它就需要24分钟。(加上我们在第一个方法中设置的阈值)

original video length 24 minute
24 min *60000 = 1,440,000 miliseconds 
1,440,000 % 100 = 14,400 milisecond is needed to download one percent

检查浏览器代理

当您正在提供网页和视频链接或接受进度更新请求时,您可以查看浏览器代理。如果它是不同的,然后禁止用户。

请注意,一些旧的浏览器不会传递此信息。因此,当视频请求和网页请求都没有浏览器代理时,可以忽略这一点。但是如果一个请求有,而另一个没有,那么你应该禁止这个用户。

为了解决这个问题,用户可以手动将浏览器代理头设置为与他们用来捕获下载链接的无头浏览器相同。

检查引用标头

当引用者不是你的主机URL或你提供视频的页面URL时,你可以禁止该用户,因为他们将下载链接放在另一个选项卡或另一个应用程序中。甚至对于进度更新请求也可以这样做。

这样做的要求是有一个视频和显示该视频的页面的映射。你可以创建一些惯例或模式来理解URL应该是什么,这取决于你的设计。

为了解决这个问题,用户可以在下载视频时手动设置与下载页面URL相等的referrer头。

计算请求之间的时间间隔

if you receive so many requests that the time between them is the same, then you should block the user. you should put this to capture how much is time between the video link generation request. if they are the same (plus/minus some threshold) and it happens more than a number of times, then you can ban the user. because if there is a bot that is going to crawl your website or videos, then usually they have the same sleep time between their request. so if you receive each request, for example, every 1.3(plus/mins some deviation) minutes. then you raise an alarm. for this, you can use some statistic calculation to know the deviation between the requests.

为了解决这个问题,用户可以在请求之间设置一个随机的睡眠时间。

示例代码

我有一个回购PluralSight-Downloader正在中途做它。我在5年前创建了这个回购。因为我写它是为了学习目的和自己的个人使用,到目前为止,回购没有收到任何更新,我不打算更新或使它易于使用。这只是一个可以做到的例子。

这是一个简单的解决方案,为那些希望简单地从html5视频删除右键单击“保存”选项

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

这是一个完整的解决方案禁用下载,包括右击>另存为…在上下文菜单中:

<video oncontextmenu="return false;" controlsList="nodownload">
</video>

我们最终使用了url过期的AWS CloudFront。视频将加载,但当用户右键单击并选择另存为最初收到的视频url时,该视频已过期。搜索CloudFront Origin Access Identity。

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

$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>';

尝试禁用下载视频选项

<video src="" controls controlsList="nodownload"></video>