林秀栋的技术博客

图片防盗链

文章来源

防盗链,就是防有人盗用你的链接。别人在他的网站上引用了你的资源(图片,音频),这样就会浪费你的流量,资源被引用的多了,你这边的服务器可能就扛不住挂了。

一般情况下以图片防盗链居多,我们也来看看图片防盗链是如何做出来的。

先来看个图,这个图是我在本地启了一个服务后,分别加载了百度和 360 搜索两个网站的图片链接,对应防盗链下的样子

01

百度的做法是用另外一张图片替换了,而 360 搜索的做法更粗暴,直接出现了裂图,访问 403 直接给 Forbidden 了。

那么图片防盗链是如何做到的呢?且看下图

02

图中所示,在请求头中有 Host(请求的主机)和 Referer(来源)两个参数,之所以会形成防盗链,那是因为 Host 和 referer 所对应的值不相同造成的。

下面我们就直接来实践一下,做一个图片防盗链,上菜;

// js部分
const fs = require("fs");
const path = require("path");
const http = require("http");
const url = require("url");
const getHostName = function (str) {
  let { hostname } = url.parse(str);
  return hostname;
};
http
  .createServer((req, res) => {
    let refer = req.headers["referer"] || req.headers["referrer"];
    // 请求头都是小写的
    // 先看一下refer的值,去和host的值作对比,不相等就需要防盗链了
    // 要读取文件 返回给客户端
    let { pathname } = url.parse(req.url);
    let src = path.join(__dirname, "public", "." + pathname);
    // src代表我要找的文件
    fs.stat(src, (err) => {
      // 先判断文件存不存在
      if (!err) {
        if (refer) {
          // 不是所有图片都有来源
          let referHost = getHostName(refer);
          let host = req.headers["host"].split(":")[0];
          if (referHost !== host) {
            // 防盗链
            fs.createReadStream(path.join(__dirname, "public", "./1.jpg")).pipe(
              res
            );
          } else {
            // 正常显示,如果路径存在,可以正常显示直接返回
            fs.createReadStream(src).pipe(res);
          }
        } else {
          // 正常显示,如果路径存在,可以正常显示直接返回
          fs.createReadStream(src).pipe(res);
        }
      } else {
        res.end("end");
      }
    });
  })
  .listen(8888);
<body>
  <img src="http://www.chenhd.me:8888/2.png" />
</body>

通过以上代码就完成了图片防盗链

若这里我们修改一下 hosts 文件,把 127.0.0.1 指定为两个不同的域名访问

127.0.0.1 www.chenhd.me 127.0.0.1 www.chd.me

友情提示:

  1. windows 系统修改 hosts 文件地址为 C:\Windos\System32\drivers\etc 下的 hosts 文件,拷贝 hosts 文件修改后替换即可
  2. mac 系统下较为方便通过终端直接 sudo vi /etc/hosts 修改即可

由于 html 部分我们图片引用的地址就是www.chenhd.me域名下的图片,所以这种情况属于正常访问,直接展示2.png图片了