详解php伪造Referer请求反盗链资源


Posted in PHP onJanuary 24, 2019

有些产品为了防止自己的产品被盗链访问,会采用反盗链措施,如封闭型生态的音乐网站和视频网站,他们已经为了版权付费,自然不希望你免费使用他们的资源。但因为很多人专门研究盗链,因此我们也需要了解下盗链、反盗链和逃避反盗链的原理。

盗链

引用百度百科对盗链的定义:

盗链是指服务提供商自己不提供服务的内容,通过技术手段绕过其它有利益的最终用户界面(如广告),直接在自己的网站上向最终用户提供其它服务提供商的服务内容,骗取最终用户的浏览和点击率。受益者不提供资源或提供很少的资源,而真正的服务提供商却得不到任何的收益。

常规盗链

我们知道,网站提供服务是向服务端请求一个 html 文件,这个文件中包含有 css/js 文件,也包含 img/video 标签,这些静态资源会在 html 文件加载时,依次的发起请求并填充在指定位置上,从而完成整个页面的加载。

详解php伪造Referer请求反盗链资源

因此只要拿到这个图片的 URL 并嵌入我们自己的 html 文件中,就能在我们的网站上访问,由于资源是不同的 HTTP 请求独立访问的,因此我们也能过滤源站的 html 文件。这就是最简单的盗链。

危害:在用户访问时,并没有在访问被盗链网站,但是依然会占用该网站的带宽资源,而带宽是要给运营商付费的。同时,该网站的广告、周边、宣传等资源并不会被用户访问到。

分布式盗链

分布式盗链比较复杂,需要在服务端部署专门的程序,并不针对单个网站或单个 url ,而是对全网的所有有用的资源进行盗取,并存储在自己的数据库中,并在用户实际访问时,完全转换为自己的流量。

危害:自己通过劳动、金钱、版权付费得到的资源,被盗链网站免费使用,如网店摄影图、期刊、电视剧等。并因此导致自己的会员、服务无法实现盈利。

反盗链分类

我们了解了盗链对源站的危害后,自然要通过一些手段来阻止这种行为维护自己的利益。

加水印

这是最简单的方法,通过后端程序批量对图片等资源加上水印,这样在盗链的同时,也在为自己的网站做宣传,有时甚至会主动寻求这种盗链。

资源重命名

因为盗链是通过指定的url,这个 url 中一定包含该资源的路径和名称,因此通过不定期的更改文件或目录的名称,能够快速避免盗链,但也会导致正在下载的资源被中断。

限制引用页

http 请求的头部信息中,有一个字段: referer ,它代表这个请求是从哪个页面发起的,如果是单独在页面中打开或者服务端请求的,则这个字段为空。因此我们可以通过 referer 这个字段的值做限制,如果是自己认可的页面,则返回资源,否则,禁止该请求。但是由于每次都要打开一个白名单的文件做 url 匹配,因此会降低性能。

加密认证

在客户端通过将用户认证的信息和资源的名称进行组合后加密,将加密的字符串作为 url 的参数发起请求,在服务端进行解密并认证通过后,才会返回请求的资源。这个方式主要用于防范分布式盗链。

反盗链程序

上面的3种反盗链方式,我们常用的是第三种,通过 referer 属性来完成反盗链,今天也主要分享这一种方法的反盗链与防反盗链。

后端程序限制

这种限制需要消耗服务端计算资源,因此不如 Nginx 限制常用。

$from = parse_url($_SERVER['HTTP_REFERER']);
if ($from['host']!='xxx.com' && $from['host']!='www.xxx.com') {
  die('你丫在盗链');
}

Nginx 限制

通过修改 nginx 配置文件可以做到,修改完成后记得重启 nginx

// 这里指定需要防盗链的资源,如gif/jpg等
location ~* \.(gif|jpg|png|jpeg)$ {
  // 设置资源的过期时间
  expires 30d;
  // 设置合法的引用页,也就是防盗链的白名单;
  // none blocked保证用户在新页面打开时依然能够打开,如果不希望用户能够保存删掉这两项
  valid_referers none blocked *.hugao8.com *.baidu.com *.google.com;
  // 对于非法的引用页,可以重写图片,也可以直接返回403或404页面
  if ($invalid_referer) {
    rewrite ^/http://www.it300.com/static/images/404.jpg;
    #return 404;
  }
}

Referer-Policy

Referer 首部包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 首部识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。

Referer 属性出现在请求头中,也在请求头中被设置,但是在浏览器的安全策略里,该值无法被 js 所指定:

$.ajax({
    url: 'http://www.baidu.com',
    beforeSend(xhr) {
      // 在发送ajax请求前设置header头部
      xhr.setRequestHeader("Referer", "http://translate.google.com/");
      xhr.setRequestHeader("User-Agent", "stagefright/1.2 (Linux;Android 5.0)");
    },
    success(data) {
      console.log(data);
    },
    error(err) {
      console.log(err);
    }
});

然而浏览器会报错:

详解php伪造Referer请求反盗链资源

那么 Referer 是怎么被自动设置的呢?这个得看 Referer-Policy属性 是怎么定义的:

  • no-referrer : 整个 Referer 首部会被移除。访问来源信息不随着请求一起发送。
  • no-referrer-when-downgrade (默认值): 在没有指定任何策略的情况下用户代理的默认行为。在同等安全级别的情况下,引用页面的地址会被发送(HTTPS->HTTPS),但是在降级的情况下不会被发送 (HTTPS->HTTP)。
  • origin : 在任何情况下,仅发送文件的源作为引用地址。例如 https://example.com/page.html 会将 https://example.com/ 作为引用地址。
  • origin-when-cross-origin : 对于同源的请求,会发送完整的URL作为引用地址,但是对于非同源请求仅发送文件的源。
  • same-origin : 对于同源的请求会发送引用地址,但是对于非同源请求则不发送引用地址信息。
  • strict-origin : 在同等安全级别的情况下,发送文件的源作为引用地址(HTTPS->HTTPS),但是在降级的情况下不会发送 (HTTPS->HTTP)。
  • strict-origin-when-cross-origin : 对于同源的请求,会发送完整的URL作为引用地址;在同等安全级别的情况下,发送文件的源作为引用地址(HTTPS->HTTPS);在降级的情况下不发送此首部 (HTTPS->HTTP)。
  • unsafe-url : 无论是同源请求还是非同源请求,都发送完整的 URL(移除参数信息之后)作为引用地址。

这个值可以通过三种方式来设置:

<meta name="referrer" content="origin">
<a href="http://example.com" rel="external nofollow" rel="external nofollow" referrerpolicy="origin">
<a href="http://example.com" rel="external nofollow" rel="external nofollow" rel="noreferrer">

防反盗链

前端 JS 不能在头部设置 Referer 字段,和跨域一样是因为浏览器的安全策略,那么同样的在服务端进行请求就不会有这些限制,我们在服务端请求时就可以自由的修改 Referer 字段。

我们通过简单的 PHP 例子来完成这个功能:

<?php
$url = 'http://t11.baidu.com/it/u=3008889497,862090385&fm=77';
$refer = 'https://www.baidu.com';
$ch = curl_init();
//以url的形式 进行请求
curl_setopt($ch, CURLOPT_URL, $url);
//以文件流的形式 进行返回 不直接输出到浏览器
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//浏览器发起请求 超时设置
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
//伪造来源地址 
curl_setopt ($ch, CURLOPT_REFERER, $refer);
$file = curl_exec($ch);
curl_close($ch);
header('Content-Type: text/html');
// 对图片进行base64编码,然后返回给前端展示
$file = base64_encode($file);
echo "<img src='data:image/jpeg;base64,{$file}' />";
?>

我们第一次请求注释了 伪造来源地址 这一行,第二次请求不注释这一行,这样可以验证执行结果:

详解php伪造Referer请求反盗链资源

详解php伪造Referer请求反盗链资源

总结

盗链和反盗链是一个对立面,技术不断升级,最终的目标也是为了开放资源和保护知识产权。在互联网生态里,我们通过反盗链保护我们的利益,也使用防反盗链的这种方式来扩大我们的内容,无论站在哪一方,都需要做到知己知彼。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP 翻页 实例代码
Aug 07 PHP
全世界最小的php网页木马一枚 附PHP木马的防范方法
Oct 09 PHP
修改destoon会员公司的伪静态中的com目录的方法
Aug 21 PHP
ThinkPHP连接数据库的方式汇总
Dec 05 PHP
curl和libcurl的区别简介
Jul 01 PHP
ThinkPHP表单数据智能写入create方法实例分析
Sep 27 PHP
PHP简单获取多个checkbox值的方法
Jun 13 PHP
php 广告点击统计代码(php+mysql)
Feb 21 PHP
PHP实现的AES双向加密解密功能示例【128位】
Sep 03 PHP
PHP自定义错误处理的方法分析
Dec 19 PHP
phpinfo无法显示的原因及解决办法
Feb 15 PHP
深入理解PHP+Mysql分布式事务与解决方案
Dec 03 PHP
PHP的mysqli_stat()函数讲解
Jan 23 #PHP
PHP的mysqli_ssl_set()函数讲解
Jan 23 #PHP
PHP的mysqli_sqlstate()函数讲解
Jan 23 #PHP
PHP的mysqli_set_charset()函数讲解
Jan 23 #PHP
PHP的mysqli_select_db()函数讲解
Jan 23 #PHP
PHP的mysqli_rollback()函数讲解
Jan 23 #PHP
PHP单元测试框架PHPUnit用法详解
Jan 23 #PHP
You might like
php集成环境xampp中apache无法启动问题解决方案
2014/11/18 PHP
百度工程师讲PHP函数的实现原理及性能分析(一)
2015/05/13 PHP
PHP解决高并发的优化方案实例
2020/12/10 PHP
Jquery 选中表格一列并对表格排序实现原理
2012/12/15 Javascript
js生成动态表格并为每个单元格添加单击事件的方法
2014/04/14 Javascript
Jquery 点击按钮自动高亮实现原理及代码
2014/04/25 Javascript
sogou地图API用法实例教程
2014/09/11 Javascript
jQuery控制div实现随滚动条滚动效果
2016/06/07 Javascript
浅谈addEventListener和attachEvent的区别
2016/07/14 Javascript
Nodejs多站点切换Htpps协议详解及简单实例
2017/02/23 NodeJs
Vue.directive自定义指令的使用详解
2017/03/10 Javascript
JavaScript实现星星等级评价功能
2017/03/22 Javascript
js微信应用场景之微信音乐相册案例分享
2017/08/11 Javascript
pace.js和NProgress.js两个加载进度插件的一点小总结
2018/01/31 Javascript
详解微信小程序scroll-view横向滚动的实践踩坑及隐藏其滚动条的实现
2019/03/14 Javascript
Vue实现固定定位图标滑动隐藏效果
2019/05/30 Javascript
微信小程序之数据绑定原理解析
2019/08/14 Javascript
JavaScript 绘制饼图的示例
2021/02/19 Javascript
[01:04:22]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 IG vs EG
2018/04/01 DOTA
Python处理JSON数据并生成条形图
2016/08/05 Python
Python实现判断字符串中包含某个字符的判断函数示例
2018/01/08 Python
Python3实现爬虫爬取赶集网列表功能【基于request和BeautifulSoup模块】
2018/12/05 Python
python 魔法函数实例及解析
2019/09/25 Python
python 实现一个简单的线性回归案例
2020/12/17 Python
html5 canvas里绘制椭圆并保持线条粗细均匀的技巧
2013/03/25 HTML / CSS
使用phonegap进行提示操作的具体方法
2017/03/30 HTML / CSS
百思买加拿大:Best Buy Canada
2018/03/20 全球购物
size?法国官网:英国伦敦的球鞋精品店
2020/03/15 全球购物
体育教师工作总结的自我评价
2013/10/10 职场文书
酒店出纳岗位职责
2013/12/29 职场文书
《分一分》教学反思
2014/04/13 职场文书
2014年文明创建工作总结
2014/11/25 职场文书
监考失职检讨书
2015/01/26 职场文书
复活读书笔记
2015/06/29 职场文书
情人节单身感言
2015/08/03 职场文书
2019年暑期安全广播稿!
2019/07/03 职场文书