字节跳动Tiktok团队北上广深杭急招前后端开发,绿色内推邮箱:sunmaoyu@bytedance.com

图片和视频防盗链简单介绍

一. 防盗链原理

http 协议中,如果从一个网页跳到另一个网页,http 头字段里面会带个 Referer。图片服务器通过检测 Referer 是否来自规定域名,来进行防盗链。

 

设置突破防盗链方法

1. 使用apache文件FileMatch限制,在httpd.conf中增加 ( 其实也可以将把下面的语句存成一个.htaccess文件),并放到你的网站的根目录(就是www/html目录),这样子别人就没有办法盗连你的东东了~~

SetEnvIfNoCase Referer "^http://kuaishou.com/" local_ref=1  
  
Order Allow,Deny  
Allow from env=local_ref  
Allow from 127.0.0.1   

 

2. 使用rewrite,需要增加apache的mode_rewrite,支持.htaccess文件目录权限限制 
在虚拟主机根目录增加.htaccess文件,描述从定向,把非本地地址refer的图片文件都从定向到警告图片或者警告网页上。 
 

    RewriteEngine on

  RewriteCond %{HTTP_REFERER} !^$ [NC]

  RewriteCond %{HTTP_REFERER} !simcole.cn [NC]

  RewriteCond %{HTTP_REFERER} !zhuaxia.com [NC]

  RewriteCond %{HTTP_REFERER} !google.com [NC]

  RewriteCond %{HTTP_REFERER} !baidu.com [NC]

  RewriteCond %{HTTP_REFERER} !bloglines.com [NC]

//这部分是判断是否盗链,如果以上条件都成立(即访问图片的请求,既不是直接输入网址,也不是来自simcole.cn,也不是来自zhuaxia.com,也不是来自google.com,也不是来自baidu.com,也不是来自bloglines.com 的话),就执行下列转向:

  RewriteRule .(jpg|gif|png|bmp|swf|jpeg) /image/replace.gif [R,NC,L]

//意思是让所有盗链 img 目录下 jpg、gif、png、bmp、swf、jpeg 文件的网页,显示的图片都用 image 目录下的 replace.gif 图片替换掉。
注意替换显示的图片不要放在设置防盗链的 img 目录下。如果照上面的规则判断出图片请求不是盗链的,就执行以下转向:

  RewriteRule ^(.*)$ http://image.simcole.cn/image/$1 [L]  

//意思是对 img 目录下所有的请求都转向到目标服务器,比如有个图片原来的 url 是 http://www.bebecn.com/img/girl.jpg ,现在就会转到 http://image.bebecn.com/image/girl.jpg 去  

 

3. 通过php直接获取资源,在php中进行拦截

$referer = $_SERVER['HTTP_REFERER']; //HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。  
$selfurl = $_SERVER['HTTP_HOST'];//在php中,我们一般通过$_SERVER['HTTP_HOST']来活得URL中网站的域名或者ip地址。  
if(false == strpos($referer,$selfurl))  
{  
echo '非法盗链!';  
exit(1);  
}  

 4. nginx防盗链

location ~* \.(gif|jpg|png|bmp)$ {
    valid_referers none blocked *.ttlsa.com server_names ~\.google\. ~\.baidu\.;
    if ($invalid_referer) {
        return 403;
        #rewrite ^/ http://www.ttlsa.com/403.jpg;
    }
}

参数说明:

none:“Referer” 来源头部为空的情况

blocked:“Referer”来源头部不为空,但是里面的值被代理或者防火墙删除了,这些值都不以http://或者https://开头.

server_names:“Referer”来源头部包含当前的server_names(当前域名)

 

5. nodejs express模块防盗链

var express = require('express'),
  path = require('path'),
  app = express();
  
var AntiLeech = require('express-anti-leech');

// 允许引用的域名白名单
var hosts = ['localhost', 'localhost:8004'];

// 反盗链类型
var exts = ['.png', '.jpg', '.jpeg', '.gif', '.swf', '.flv'];

// 盗链默认指向图片
var pictrue = "/images/default.png";

app.use(AntiLeech({
  allow: hosts,
  exts: exts,
  log: console.log, // 你也可以使用自己的方法来记录
  default: pictrue
}));

// 请在调用静态资源之前先使用反盗链模块
app.use(express.static(path.join(__dirname, 'public')));
app.set('port', process.env.PORT || 8004);

app.get('/', function(req, res) {
  res.redirect("/index.html");
});

app.listen(app.get('port'), function() {
  console.log("Express test server listening on http://localhost:" + app.get('port'));
});

 

二. 突破防盗链

1. referer为空

若不发送Referer,也就是没有来源。那么官方那边,就认为是从浏览器直接访问的,所以就能加载正常的图片

a. https访问http

如果盗用网站是 https 的 protocol,而图片链接是 http 的话,则从 https 向 http 发起的请求会因为安全性的规定,而不带 referer,从而实现防盗链的绕过

b.

某些开启隐私模式的浏览器中,或https页面引用下,referer是空的

c. 设置头部信息

Nodejs:
res.writeHead(200, {
    'Content-Type': 'image/*'
});
let url = req.query.url;
if (!url) {
    res.send("");
    return false;
}
superagent.get(req.query.url)
    .set('Referer', '')
    .set("User-Agent",
        'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36 Core/1.47.933.400 QQBrowser/9.4.8699.400'
    )
    .end(function(err, result) {
        if (err) {
            //res.send(err);
            return false;
        }
        res.end(result.body);
        return;
    });

 

2. 代码内请求伪造referer

PHP:
$http = new Http("http://www.baidu.com/img/avatar.jpg");
$http->setHeader('Referer:http://www.baidu.com/');

 

3. 利用iframe伪造请求referer

function showImg( url ) {
        var frameid = 'frameimg' + Math.random();
        window.img = '<img id="img" src=\''+url+'?'+Math.random()+'\' /><script>window.onload = function() { parent.document.getElementById(\''+frameid+'\').height = document.getElementById(\'img\').height+\'px\'; }<'+'/script>';
        document.write('<iframe id="'+frameid+'" src="javascript:parent.img;" frameBorder="0" scrolling="no" width="100%"></iframe>');
}

 

4. meta标签控制referer

如果页面中包含了如下 meta 标签,所有从当前页面中发起的请求将不会携带 referer:

<meta name="referrer" content="never">

如果页面中包含了如下 meta 标签,则从当前页面中发起的 http请求将只携带 origin 部分(注:根据原文中的语境,我理解这里的 origin 是包含了 schema 和 hostname 的部分 url,不包含 path 等后面的其他 url 部分),而不是完整的 URL :

<meta name="referrer" content="origin">

注意:在使用本文中所述的 meta 标签的时候,浏览器原有的 referer 策略将被打破,比如从 http 协议的页面跳转到 https 的页面的时候,如果设置了适当的值,也会携带 referer。

技术细节:

referer 的 metedata 参数可以设置为以下几种类型的值:

never
always
origin
default

如果在文档中插入 meta 标签,并且 name 属性的值为 referer,浏览器客户端将按照如下步骤处理这个标签:

1.如果 meta 标签中没有 content 属性,则终止下面所有操作
2.将 content 的值复制给 referrer-policy ,并转换为小写
3.检查 content 的值是否为上面 list 中的一个,如果不是,则将值置为 default

上述步骤之后,浏览器后续发起 http 请求的时候,会按照 content 的值,做出如下反应(下面 referer-policy 的值即 meta 标签中 content 的值):

1.如果 referer-policy 的值为never:删除 http head 中的 referer;
2.如果 referer-policy 的值为default:如果当前页面使用的是 https 协议,而正要加载的资源使用的是普通的 http 协议,则将 http header 中的 referer 置为空;
3.如果 referer-policy 的值为 origin:只发送 origin 部分;
4.如果 referer-policy 的值为 always:不改变http header 中的 referer 的值,注意:这种情况下,如果当前页面使用了 https 协议,而要加载的资源使用的是 http 协议,加载资源的请求头中也会携带 referer。

 

 

三. 防御反防盗链

关于防御方法,有以下3点:

  1、不允许referer为空(不建议,因在某些开启隐私模式的浏览器中,或https页面引用下,referer是空的)
  2、地址变更(lighttpd的是根据有效时间,nginx的根据是md5,IP地址变化)
  3、登录校验(如必须登录网站帐号后才能访问)

 

扩展一:视频防盗链和加密

 

视频加密技术分为两种:

 

1. 防盗链:通过验证的用户才能访问到没有加密的视频内容,这种方案存在视频很容易就被下载的风险,严格来说这不属于加密。这种方式其实是资源访问授权,它实现起来简单。

2. 加密视频本身:通过对称加密算法加密视频内容本身,用户获得加密后的视频内容,通过验证的用户可以获取解密视频的密钥,在客户端解密后播放。这种方式实现起来流程复杂会带来更多的计算量。

 

 

市面上常见的防盗手段:

1.设置 referer 白名单,非白名单内的一律拒绝访问

2.在 URL 中添加 token 校验,使用私有 key 和 time 实时计算 token,服务器作校验

3.在第2条的基础上,使用 https POST token 参数,增加抓取难度

4.使用 HLS(m3u8) 自带的加密功能,加密传输数据,没有密码无法播放

5.使用数字版权保护(DRM)技术

还有一些不太常见的手段:

1.使用HTTPS客户端证书,服务器可以对客户端进行识别(目前常见的HTTPS是服务器端证书)

2.使用HLS(m3u8)自带的加密功能,并对密码做二次处理,客户端经过两次解密才能得到原数据

3.对视频编码进行二次处理,解码时需要知道算法,否则无数得到原数据,见于海康监控系统

详解见:http://imweb.io/topic/59819d7bf8b6c96352a593ff

 

扩展二:防止网站被镜像,被iframe

1.防止网站被镜像(被恶意解析和转发等)

现象:他人域名访问到的是我的网站解析的ip地址我的

解决方法:

http.ini里可以这样写

"RewriteCond Host: !^www.web\.cn$  RewriteRule (.*) http\://www\.web\.cn$1 [I,RP]"

.htaccess里可以这样写

“RewriteCond %{HTTP_HOST} !^www.web.cn$ [NC] RewriteRule ^(.*)$ http://www.web.cn/$1 [L,R=301]”

代码的意思非常简单:访问这个网站的域名如果不是"www.web.cn"就自动跳转到"www.web.cn"上。这样设置就不怕自己辛辛苦苦维护的网站被别人镜像了。

2.防止网址被iframe

代码:在页面底部或其它公用部位加入如下代码

<script type=”text/javascript> 
   if(window!=parent) 
  window.top.location.href = window.location.href; 
< /script> 

代码的意思也很简单,用js方法检测地址栏域名是不是当前网站绑定的域名,如果不是,则跳转到绑定的域名上来,这样就不怕网站被别人iframe了。

3.如何防止网站被复制保存或者被下载

参考文档:http://www.3lian.com/edu/2013/10-12/101296.html

 

 

参考:

http://www.freebuf.com/news/57497.html

https://www.zhihu.com/question/35044484/answer/350722473

https://www.cnblogs.com/lydiawork/p/7838153.html

https://blog.csdn.net/enweitech/article/details/45745171

https://www.zhihu.com/question/64369225/answer/219528505

 


 

posted @ 2018-03-26 11:58  冒雨ing  阅读(26339)  评论(3编辑  收藏  举报