Referer;盗链;防盗链的工作原理

文章详细介绍了Referrer-policy的用途和设置方法,包括如何通过meta标签和元素属性控制referer信息。同时,文章探讨了防盗链的概念,解释了其工作原理,并提供了一些绕过图片防盗链的方法。此外,还讨论了服务器端如何利用nginx和自定义逻辑来实现防盗链保护。
摘要由CSDN通过智能技术生成

目录

Referrer-policy

如何设置referer

盗链

防盗链的工作原理

绕过图片防盗链

设置meta

设置referrerpolicy="no-referrer"

客户端在请求时修改header头部

利用https网站盗链http资源网站,refer不会发送

常见防盗链方法

利用nginx

服务器端判断referer

防止网址被 iframe


Referer请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用Referer(注:正确英语拼写应该是referrer,由于早期HTTP规范的拼写错误,为了保持向后兼容就一直延续下来)请求头识别访问来源,可能会以此统计分析、日志记录以及缓存优化等。

 

  注: Referer请求头可能会暴露用户的浏览历史、涉及到用户的隐私问题。

Referrer-policy

Referrer-policy作用就是为了控制请求头中referer的内容

一定程度上可以防御CSRF

包含以下值:

  • no-referrer : 整个referee首部会被移除,访问来源信息不随着请求一起发送。

  • no-referrer-when-downgrade : 在没有指定任何策略的情况下用户代理的默认行为。在同等安全级别的情况下,引用页面的地址会被发送(HTTPS->HTTPS),但是在降级的情况下不会被发送 (HTTPS->HTTP).

  • origin: 在任何情况下,仅发送文件的源作为引用地址。例如 https://example.com/page.html 会将 Example Domain 作为引用地址。

  • origin-when-cross-origin: 对于同源的请求,会发送完整的URL作为引用地址,但是对于非同源请求仅发送文件的源。

  • same-origin: 对于同源的请求会发送引用地址,但是对于非同源请求则不发送引用地址信息。

  • strict-origin: 在同等安全级别的情况下,发送文件的源作为引用地址(HTTPS->HTTPS),但是在降级的情况下不会发送 (HTTPS->HTTP)。

  • strict-origin-when-cross-origin: 对于同源的请求,会发送完整的URL作为引用地址;在同等安全级别的情况下,发送文件的源作为引用地址(HTTPS->HTTPS);在降级的情况下不发送此首部 (HTTPS->HTTP)【不会发送referrer】。

  • unsafe-url: 无论是同源请求还是非同源请求,都发送完整的 URL(移除参数信息之后)作为引用地址。(最不安全)

浏览器兼容性icon-default.png?t=MBR7https://caniuse.com/?search=referer-policy

如何设置referer

  1. 在HTML里设置meta

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

 

或者用<a>、<area>、<img>、<iframe>、<script> 或者 <link> 元素上的 referrerpolicy 属性为其设置独立的请求策略。 如:

<script src='/javascripts/test.js' referrerpolicy="no-referrer"></script>

 

 

未加referrerpolicy属性的link元素:  

盗链

 盗链是指在自己的页面上展示一些并不在自己服务器上的一些内容, 获取别人的资源地址,绕过别人的资源展示页面,直接在自己的页面上向最终用户提供此内容。 一般被盗链的都是图片、 可执行文件、 音视频文件、压缩文件等资源。通过盗链的手段可以减轻自己服务器的负担

比如在自己页面里引入百度贴吧里的一张照片:

<body>
    <img src="https://tiebapic.baidu.com/forum/w%3D580%3B/sign=f88eb0f2cf82b9013dadc33b43b6ab77/562c11dfa9ec8a135455cc35b203918fa1ecc09c.jpg"> 
</body>

但实际上是无法展示的(如下图),之所以无法展示是因为百度的图片做过防盗链处理

防盗链的工作原理

通过Referer或者签名,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以追踪到显示它的网页地址 一旦检测到来源不是本站,即进行阻止或者返回指定的页面

绕过图片防盗链

那么现在的很多网站是如何利用referer来进行防图片盗链的呢?

三种情况下允许引用图片:

  1. 本网站。

  2. 无referer信息的情况。(服务器认为是从浏览器直接访问的图片URL,所以这种情况下能正常访问)

  3. 授权的网址。

我们只能从情况2入手,通过设置referer为空进行绕过防盗链。

设置meta

<meta name="referrer" content="no-referrer" />

设置referrerpolicy="no-referrer"

客户端在请求时修改header头部

参考内容icon-default.png?t=MBR7http:// https://juejin.cn/post/6844903892170309640

利用https网站盗链http资源网站,refer不会发送

原理如下:

但,因为Chrome浏览器更新了,不允许HTPPS降级为HTTP了,所以此方法无用

常见防盗链方法

防盗链一般有下面几种方式:

  1. 动态文件名,或者定期修改文件名称或路径

  2. 判定引用地址,一般是判断浏览器请求时HTTP头的Referer字段的值

  3. 使用登录验证,cookie

  4. 图片加水印

  5. ...

利用nginx

ngx_http_referer_module用于阻挡来源非法域名的请求 nginx指令valid_refers,全局变量$invalid_refer 对资源的防盗链nginx配置为

location ~.*\.(gif|jpg|png|bmp|flv|swf|rar|zip)$
{
    valid_referers none blocked test.com *.test.com;   // 加none的目的是确保浏览器可以直接访问资源
    if($invalid_referer)
    {
        #return 403;  // 直接返回403
        rewrite ^/ http://www.test.com/403.jpg; // 返回指定提示图片
    }
}

这种方法是在server或者location段中加入:valid_referers。这个指令在referer头的基础上为 $invalid_referer 变量赋值,其值为0或1。如果valid_referers列表中没有Referer头的值, $invalid_referer将被设置为1。 如果 $invalid_referer等于 1,在if语句中返回一个 403 给用户,这样用户便会看到一个 403 的页面, 如果使用下面的rewrite,那么盗链的图片都会显示 403.jpg。 该指令支持none和blocked:

  • 其中none表示空的来路,也就是直接访问,比如直接在浏览器打开一个文件

  • blocked表示被防火墙标记过的来路,*..com表示所有子域名

但是传统的防盗链也会存在一些问题,因为refer是可以伪造的, 所以可以使用加密签名的方式来解决这个问题。 什么是加密签名?就是当我们请求一个图片的时候,我要给它带一些签名过去,然后返回图片的时候我们判断下签名是否正确,相当于对一个暗号。

服务器端判断referer

我们能通过对比req.headers['referer']和req.url中的host来确认资源请求是否是别的站点发来的。 接着,当我们知道了资源请求的来源,我们就能通过一系列手段来决定是否响应请求以及怎样响应。 通常的做法是设置一个白名单,在白名单内的请求我们就响应,否则就不响应。  

let http = require("http");
let fs = require("fs");
let url = require("url");
let path = require("path");
// 白名单
const whiteList = ["localhost:8080"];

/**
 * 三种情况下允许引用图片:
 * 1. 本网站
 * 2. 无referer信息的情况。(服务器认为是从浏览器直接访问的图片URL,所以这种情况下能正常访问)
 * 3. 授权的网址。(配置白名单)
 */

http
  .createServer(function (req, res) {

    let refer = req.headers["referer"] || req.headers["refer"];
    console.log('refer----', refer, req.url);
    res.setHeader("Access-Control-Allow-Origin", "*");
    if (refer) {
      let referHostName = url.parse(refer, true).host;
      let currentHostName = url.parse(req.url, true).host;
      console.log(referHostName, currentHostName, '--==')
      // 当referer不为空, 但host未能命中目标网站且不在白名单内时, 返回错误的图
      if (
        referHostName != currentHostName &&
        whiteList.indexOf(referHostName) == -1
      ) {
        res.setHeader("Content-Type", "image/jpeg");
        fs.createReadStream(path.join(__dirname, "/src/img/403.jpg")).pipe(res);
        return;
      }
    }
    // 当referer为空时, 返回正确的图
    res.setHeader("Content-Type", "image/jpeg");
    fs.createReadStream(path.join(__dirname, "/src/img/1.jpg")).pipe(res);
    
  })
  .listen(9999);

利用http启动一个客户端:

client.js

let http = require("http");
let fs = require("fs");
let url = require("url");
let path = require("path");

// 创建服务器
http.createServer(function (req, res) {
  let staticPath = path.join(__dirname, "src");
  let pathObj = url.parse(req.url, true);

  if (pathObj.pathname === "/") {
    pathObj.pathname += "index.html";
  }
  //  读取静态目录里面的文件,然后发送出去
  let filePath = path.join(staticPath, pathObj.pathname);
  fs.readFile(filePath, "binary", function (err, content) {
    if (err) {
      res.writeHead(404, "Not Found");
      res.end("<h1>404 Not Found</h1>");
    } else {
      res.writeHead(200, "Not Found");
      res.write(content, "binary");
      res.end();
    }
  });
}).listen(8080);

index.html  

<div id="container">
    <img src="http://localhost:9999">
</div>

防止网址被 iframe

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

// 用js方法检测地址栏域名是不是当前网站绑定的域名,如果不是,则跳转到绑定的域名上来,这样就
不怕网站被别人iframe了
if(window!=parent) {
    window.top.location.href = window.location.href; 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,您的问题是如何获取referer中的请求参数,以及如何通过request获取referer请求头实现防盗链。 首先,referer是HTTP请求头中的一个字段,用于表示当前请求是从哪个页面发起的。如果当前请求是从某个页面跳转过来的,则referer中会包含跳转页面的URL,如果没有则为null。 如果您想要获取referer中的请求参数,可以使用Java中的URL类来解析referer中的URL,然后通过其getQuery方法获取请求参数。以下是一个简单的示例代码: ```java String referer = request.getHeader("referer"); if (referer != null) { URL url = new URL(referer); String query = url.getQuery(); // 处理请求参数 } ``` 另外,您提到了防盗链的问题。防盗链是指通过某些手段,禁止其他网站直接链接到您的资源,以保护资源的安全和版权。其中一种常见的防盗链方式就是通过判断referer请求头来实现。 具体实现方式是在服务器端判断referer请求头中的URL是否属于当前网站的域名范围内,如果不属于则返回错误信息。 以下是一个简单的示例代码: ```java String referer = request.getHeader("referer"); if (referer != null && !referer.startsWith("http://www.yourdomain.com")) { // 不允许访问 response.setStatus(403); return; } // 允许访问 ``` 注意,这种方式虽然可以简单地防止盗链,但是referer请求头是可以伪造的,因此并不是绝对可靠的防盗链方式。需要根据具体情况进行综合考虑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戲子 鬧京城°ぃ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值