小工具知识网

当前位置: 首页 > 行业知识 > 围绕http请求头中Referer展开的一些知识

行业知识

围绕http请求头中Referer展开的一些知识

2026-11-16 03:53:14 来源:互联网转载

1. 什么是referer?

跳转过去记得按一下f12点击网络请求详情,再刷新一下,就可以看见referer字段:

当我们尝试在浏览器内部直接输入这熟悉的网址时,此时刷新后则是这样一番景象:

于是你就明白了referer的基本用途,它是存在于http请求头内部的用于标识访问者来源网页的标识字段。通常在普通用户的访问下是不会出现的,常常出现于各个网页之间的相互跳转。

说到这里你想到了什么,各个网页?嗯…记得这块在网页里面引用别人的东西好像还挺多的。直接把人家的图片地址写下来,就能显示,可方便了。对,这种行为就是盗图,当然只要是可以在网页上访问的网络资源,基本上都会面临这样一种情况:被盗取资源。盗取链接与防止盗取链接形成了一个经久不衰的话题。那么今天我们就通过几个小例子来体会一下盗图与防盗图的斗争吧。好好的理解一下关于referer字段的故事。

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

真有人为了这事情发博客吐槽…哈哈 详细历史见吐槽内容

2. Referrer-policy

言归正传,学习!显然,注意刚刚访问百度的同学可以细心的发现referrer-policy这个引用者策略,其规定了referer的具体使用规则。不同的设置如下给出:

  • no-referrer : 整个referee首部会被移除,访问来源信息不随着请求一起发送。
  • 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(移除参数信息之后)作为引用地址。(最不安全了)

    3.设置referrer

    可以在HTML里面设置meta标签

     

    也可以用、、、、 或者 元素上的 referrerpolicy 属性为其设置独立的请求策略。

    比如:

     

    注意,如果不对页面进行处理的话,默认的referer-policy的数值是 strict-origin-when-cross-origin

    4.绕过防盗链

    前面我们说过防盗链的工作原理,其就是通过Referer或者签名,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以追踪到显示它的网页地址 一旦检测到来源不是本站,即进行阻止或者返回指定的页面。

    那么要绕过它就至少的满足下面的三个条件之一:

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

    显然,方法1、3均无法实现。留给我们的方法就只有想办法去除自己在访问时的referer字段了。

    4.1 利用https降级访问http资源网站

    当我们的目标被盗网站的策略采用默认策略时,我们可以利用访问主动降级的方式将目标图片盗链下来。也就是说我们可以在https的网页中用http请求另一个https网站的资源。此时可以不发送我们的referer字段,达到绕过防盗链的效果。(由于浏览器的升级,现在这种操作已经被禁止了。)虽然如此,我们还是尝试这复现一下这一操作。

    示例环境:centos7 安装nodejs环境

    用nodejs同时模拟出”盗图人“和“拥图人”。我们使用古老的浏览器尝试访问网页见证这一古老的偷图方法。

    1.生成自签名证书

    如何在本地为本地的web服务创建自签名成了我们要解决的第一个问题。按照以下步骤创建对应的证书以及签名。在此之前应当创建对应的文件夹:

    [root@blackstone ceshi]# mkdir demo01[root@blackstone ceshi]# mkdir -p ./demo01/server/keys[root@blackstone ceshi]# mkdir -p ./demo01/server/src[root@blackstone ceshi]# mkdir -p ./demo01/client/src[root@blackstone ceshi]# mkdir -p ./demo01/client/keys[root@blackstone ceshi]# mkdir -p ./demo01/ca[root@blackstone ceshi]# tree demo01demo01├── ca├── client│   ├── keys│   └── src└── server    ├── keys    └── src

    好,接下来到这个demo01目录下,进行证书的构造

    #1.生成私钥// 生成服务器端私钥   openssl genrsa -out server/keys/server.key 1024   // 生成客户端私钥  openssl genrsa -out client/keys/client.key 1024#2.生成公钥openssl rsa -in server/keys/server.key -pubout -out server/keys/server.pemopenssl rsa -in client/keys/client.key -pubout -out client/keys/client.pem#3.CA证书自签名#3.1 创建CA私钥openssl genrsa -out ca/ca.key 1024#3.2 生成CA的CSR文件与crt#生成csropenssl req -new -key ca/ca.key -out ca/ca.csr#生成crtopenssl x509 -req -in ca/ca.csr -signkey ca/ca.key -out ca/ca.crt#3.3 为server发放证书#生成csr文件openssl req -new -key server/keys/server.key -out server/keys/server.csr#签名过程需要CA的证书和私钥参与, 最终颁发一个带有CA签名的证书openssl x509 -req -CA ca/ca.crt -CAkey ca/ca.key -CAcreateserial -in server/keys/server.csr -out server/keys/server.crt#3.4 为client发放证书#生成CSR文件openssl req -new -key client/keys/client.key -out client/keys/client.csr#签名过程需要CA的证书和私钥参与, 最终颁发一个带有CA签名的证书openssl x509 -req -CA ca/ca.crt -CAkey ca/ca.key -CAcreateserial -in client/keys/client.csr -out client/keys/client.crt

    关于CA证书:为了得到签名证书,服务器端需要通过自己的私钥生成CSR(Certificate Signing Request,证书签名请求)文件。CA机构通过这个文件颁发属于该服务器端的签名证书,只要通过CA机构就能验证证书是否合法。

    上面用是自签名证书来构建安全网络的。所谓自签名证书,就是自己扮演CA机构,给自己得服务器端颁发签名证书。其过程包括了生成CA私钥、生成CSR文件、通过私钥自签名生成证书

    经过上面一通创建之后,我们使用tree确认生成无误

    2. 配置server端

    server目录下创建server.js用于建立服务

    let https = require("https");let fs = require("fs");let url = require("url");let path = require("path");// 白名单const whiteList = ["192.168.2.169:80"];const options = {  key: fs.readFileSync("./keys/server.key"),  cert: fs.readFileSync("./keys/server.crt"),};https  .createServer(options, 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);

    监听的是9999端口,用于模拟被偷服务器,在其对应的src目录下放上相应的资源

    3.配置client端

    服务端的nodejs文件client.js

    let https = require("https");let fs = require("fs");let url = require("url");let path = require("path");var options = {  hostname: "localhost",  port: 8000,  path: "/",  method: "GET",  rejectUnauthorized: false,  key: fs.readFileSync("./keys/client.key"),  cert: fs.readFileSync("./keys/client.crt"),  ca: [fs.readFileSync("../ca/ca.crt")],};// 创建服务器https.createServer(options, 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("

    404 Not Found

    "); } else { res.writeHead(200, "OK"); res.write(content, "binary"); res.end(); } });}).listen(8080);

    配置client首页文件

    [root@blackstone client]# cat ./src/index.html                client    

    client页面

    4.在浏览器上测试盗链情况

    依次分别运行server和client

    [root@blackstone server]# node server.js[root@blackstone client]# node client.js

    使用火狐浏览器测试访问:

    可以看到,尽管我们尝试进行盗链,但是因为浏览器的安全限定,无法显示偷出来的图片,我们掏出超低版本的浏览器试试。。。经测试暂时无果,这个古老的方案大抵是被禁用掉了。

    点击此处获取老版本浏览器

    4.2 使用meta

     

    可以清晰的看到,设置后发出的https请求已经没了referer字段,正常请求到了图片

    4.3 设置referrerpolicy=“no-referrer”

    在标签旁设置上这个属性就行

     

    4.4 利用iframe伪造请求referer

    function showImg(src, wrapper ) {    let url = new URL(src);    let frameid = 'frameimg' + Math.random();    window.img = `

上一篇:PHP代码美化宝典,打造优雅代码风格指南

下一篇:IDEA无法识别SpringBoot项目