原理

http 协议请求中 header 里会带个 Referer 字段。通过图片服务器检查 Referer 是否来自规定的域名(白名单),而进行防盗链。 在浏览器中输入防盗链图片地址是能直接访问的。

网络安全 - 前端程序员务必掌握的图片防盗链

原理

图片防盗链技术是一种网络安全措施,目的是防止其他网站恶意引用你的图片资源。这项技术通过检查 HTTP 协议请求中的 Referer 头部字段实现。

  • Referer: 这是一个 HTTP 请求头的一部分,指明了请求是从哪个地址发起的。这可以是网页、图像或其他资源。
  • 白名单: 一个由你设定的域名列表,指定了哪些域名被允许引用你的图片资源。
  • 检查流程: 图片服务器会检查每个请求的 Referer 字段,确认其是否来自于白名单上的域名。

应用场景

  1. 保护版权: 防止他人未经授权使用你的图像资源。
  2. 节省带宽: 避免其他网站使用你的服务器作为其图片的免费存储和传输服务。

优点

  • 直观: 通过设置一个简单的规则列表,可以快速实现防盗链。
  • 易于实现: 大多数服务器和 CDN 提供商都支持防盗链功能。

缺点

  • 误报: 有时可能会错误地阻止合法的访问。
  • 绕过: 技术熟练的攻击者或恶意用户可以修改 HTTP 头部来绕过防盗链。

实现方法

  1. 服务器配置: 修改服务器配置,设置允许引用的域名列表。
  2. 编程实现: 在应用程序中添加逻辑,检查每个请求的 Referer 字段。

简单实现防盗链图片

可以通过 nginx 配置白名单列表,不在白名单则返回 403 或者相应的处理(重定向到显示403的图片,等操作)

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

以上所有来自 *.andyhu.com 域名和域名中包含 google 和 baidu 的站点都可以访问当前站点的gif|jpg|jpeg|png|bmp|swf|flv文件资源。其他来源域(不在白名单列表)名访问则返回 403。如果被注释的 rewrite 则返回一张 403.jpg 的图片

显示第三方防盗链图片

顺这浏览器能直接访问防盗链图片的思路,不难发现,只要请求头 header 里面不携带 Referer 就能正常访问到防盗链的资源。

1.全局下 请求都不带 referer <meta name="referrer" content="no-referrer" />

标题含义
no-referrer整个 Referer 首部会被移除。访问来源信息不随着请求一起发送。
no-referrer-when-downgrade在同等安全级别的情况下,引用页面的地址会被发送(HTTPSHTTPS),但是在降级的情况下不会被发送 (HTTPSHTTP)。
origin在任何情况下,仅发送文件的源作为引用地址。例如 example.com/page.html 会将 example.com/ 作为引用地址。
origin-when-cross-origin对于同源的请求,会发送完整的URL作为引用地址,但是对于非同源请求仅发送文件的源。
same-origin对于同源的请求会发送引用地址,但是对于非同源请求则不发送引用地址信息。
strict-origin在同等安全级别的情况下,发送文件的源作为引用地址(HTTPSHTTPS),但是在降级的情况下不会发送 (HTTPSHTTP)。
strict-origin-when-cross-origin对于同源的请求,会发送完整的URL作为引用地址;在同等安全级别的情况下,发送文件的源作为引用地址(HTTPSHTTPS);在降级的情况下不发送此首部 (HTTPSHTTP)。
unsafe-url无论是同源请求还是非同源请求,都发送完整的 URL(移除参数信息之后)作为引用地址。

MDN相关文档(更详细)
小插曲(没有微信H5支付的需求可以无视次插曲)
有次我项目中为了访问第三方防盗链图片,加了这行代码。然后项目中用到了微信 H5 支付,而微信 H5 支付是需要通过从 referer 中获取当前调起H5支付的域名与申请H5支付时提交的授权域名判断域名是否一致的。所以导致我项目中微信支付一直提示 “商家存在未配置的参数”
微信H5支付报错:“商家存在未配置的参数,请联系商家解决”

微信支付开发指引

2.给某个资源添加 ReferrerPolicy 属性

例如:给图片资源添加 ReferrerPolicy 属性

<img src="xxxx.jpg" referrerPolicy="no-referrer" />
 

MDN相关文档(更详细)

3.使用第三方代理

例如:通过第三方代理访问地址为https://p9-passport.byteacctimg.com/img/user-avatar/f9166aceb85b42133f48537808cef8eb~300x300.image 的图片

<img src="https://images.weserv.nl/?url=https://p9-passport.byteacctimg.com/img/user-avatar/f9166aceb85b42133f48537808cef8eb~300x300.image"/>
 

缺点: 不稳点,第三方代理可能在国内访问不稳定,在国内没有好的推荐,小伙伴如果有好的国内的第三方代理推荐,可以在评论区 留意哈!感谢感谢!当然也可以自己做一个代理哈。

4.利用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>');
}
 

参考地址