搜索全站
性能优化 11 分钟阅读

WordPress 图片防盗链配置:Nginx 与 CDN 两种实现方案

别人直接引用你的图片,流量费你出。本文讲清 Referer 防盗链的原理与绕过方式,给出 Nginx valid_referers 配置、CDN 防盗链设置,以及比 Referer 更可靠的签名方案。

U
UFO_PF 2016-05-01 · 阅读 11 分钟
Wo 性能优化
阅读提示
本文约 4,371 字,预计阅读 11 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:图片被抄走,账单是你付

内容站最烦的一件事:文章被人整篇采集,图片直接 <img src="https://你的域名/..."> 引用。结果:

  • 别人的页面加载你的图片,消耗的是你的带宽和 CDN 流量费;
  • 采集站排名可能还比你高;
  • 更恶劣的做成图床,被大量引用,一天跑掉几十 GB 流量。

防盗链(Hotlink Protection)就是解决这个问题的:只放行来自自己站点的图片请求,其他来源返回 403 或一张占位图。

原理分析:Referer 是怎么工作的

浏览器加载 <img> 时会带上 Referer 头,标明”这个请求是从哪个页面发起的”。

GET /wp-content/uploads/2025/01/demo.jpg HTTP/1.1
Host: mimangfei.com
Referer: https://mimangfei.com/some-article/

盗链场景下:

Referer: https://spam-site.com/copy-article/

服务器检查 Referer 是否在白名单里,不在就拒绝。这就是 Referer 防盗链。

但 Referer 有几个天然缺陷,必须知道:

  1. 可伪造:用 curl 随便加个 -e 参数就能绕过。所以 Referer 防盗链只能防”浏览器直接引用”,防不了刻意盗用。
  2. 可能为空:
    – 用户在地址栏直接打开图片 URL;
    – HTTPS 页面引用 HTTP 图片(Referer 被降级策略剥离);
    – Referrer-Policy: no-referrer;
    – 部分浏览器隐私模式、部分邮件客户端。
    所以必须放行空 Referer,否则正常访客也看不到图。

  3. 爬虫不带 Referer:搜索引擎图片抓取通常不带或有自己的标识,误封会影响收录。要把百度、Google 的爬虫 UA 或域名加白。

保姆级实操

方案一:Nginx 配置(valid_referers)

在站点的 server 块里加:

location ~* \.(jpg|jpeg|png|gif|webp|bmp|ico|svg)$ {
    # 定义合法 Referer
    valid_referers none blocked
                   server_names
                   *.mimangfei.com mimangfei.com
                   *.baidu.com *.baiducontent.com
                   *.google.com *.googleusercontent.com
                   *.bing.com
                   *.so.com *.sogou.com;

    # 不在白名单内 → 返回 403
    if ($invalid_referer) {
        return 403;
    }

    expires 30d;
    access_log off;
}

参数解释:

  • none:允许 Referer 为空(必加,否则地址栏直接访问图片会 403);
  • blocked:允许 Referer 被防火墙/代理去掉了(不是完整 URL 的情况);
  • server_names:允许 server_name 里定义的所有域名;
  • 后面的是显式白名单。

更友好的做法:返回占位图而不是 403

location ~* \.(jpg|jpeg|png|gif|webp)$ {
    valid_referers none blocked server_names *.mimangfei.com;
    if ($invalid_referer) {
        # 注意:rewrite 后要用 break,避免循环
        rewrite ^/.*$ /no-hotlink.png break;
    }
    expires 30d;
}

准备一张 /no-hotlink.png(可以写”图片来自 mimangfei.com”),这样盗链者的页面上会出现你的水印图,比 403 更有宣传效果。

针对特定目录(只保护 uploads)

location ^~ /wp-content/uploads/ {
    valid_referers none blocked server_names *.mimangfei.com;
    if ($invalid_referer) {
        return 403;
    }
    expires 365d;
    access_log off;
}

配置后重载:

sudo nginx -t && sudo systemctl reload nginx

验证:

# 正常 Referer → 200
curl -I -e "https://mimangfei.com/" https://mimangfei.com/wp-content/uploads/2025/01/a.jpg

# 盗链 Referer → 403
curl -I -e "https://spam.com/" https://mimangfei.com/wp-content/uploads/2025/01/a.jpg

# 空 Referer → 200(因为配了 none)
curl -I https://mimangfei.com/wp-content/uploads/2025/01/a.jpg

方案二:CDN 控制台配置(推荐,更省事)

主流 CDN 都有”防盗链”或”Referer 防盗链”功能:

  • 阿里云 CDN:域名管理 → 访问控制 → Referer 防盗链 → 白名单,勾上”允许空 Referer”;
  • 腾讯云 CDN:域名管理 → 访问控制 → Referer 配置;
  • Cloudflare:免费版没有原生 Referer 防盗链,需要用 WAF 规则或 Firewall Rules:

(http.request.uri.path contains "/wp-content/uploads/")
and (not http.referer contains "mimangfei.com")
→ Block

  • 又拍云 / 七牛:控制台都有对应开关。

CDN 层的优势:拦在边缘节点,不消耗源站资源,配置也不需要动服务器。

方案三:签名鉴权(更可靠,防伪造)

如果图片价值高(付费课程配图、素材站),Referer 不够用,要用 URL 签名 / 鉴权:

  • 阿里云 CDN:URL 鉴权(A/B/C 三种方式);
  • 腾讯云:鉴权配置 TypeA/TypeB/TypeC;
  • 原理:URL 带一个 ?auth_key=timestamp-rand-md5hash 参数,服务端校验签名和有效期,过期或篡改即拒绝;
  • 代价:需要在 WordPress 里动态生成签名 URL,缓存时间不能长于签名有效期。

WordPress 侧生成签名 URL 的例子(阿里云 TypeA):

function mmf_sign_url( $url, $ttl = 3600 ) {
    $key       = '你的鉴权key';
    $path      = parse_url( $url, PHP_URL_PATH );
    $timestamp = time() + $ttl;
    $rand      = '0';
    $raw       = $path . '-' . $timestamp . '-' . $rand . '-0-' . $key;
    $hash      = md5( $raw );
    return $url . '?auth_key=' . $timestamp . '-' . $rand . '-0-' . $hash;
}

方案四:用插件(最省事但不推荐)

有一些”防盗链”WordPress 插件,本质是通过 .htaccess 或 PHP 输出图片。用 PHP 输出图片性能极差(每次都要启动 WordPress),除非流量极小,否则不建议。

常见踩坑

  1. 没加 none 导致正常访客看不到图:最常见的错误。地址栏直接访问、微信内置浏览器、部分 App 内嵌 WebView 都可能不带 Referer。
  2. 误封搜索引擎:百度图片、Google 图片的抓取可能不带 Referer,或带上自己的域名。误封会导致图片无法被收录。一定要把搜索引擎域名加白名单,并去百度站长平台的”抓取诊断”里验证。
  3. HTTPS 页面引用 HTTP 图:Referer 被浏览器剥离,变成空。这就是必须放行 none 的又一个原因。
  4. 案例:某站配置了防盗链后,微信里分享的文章图片全部裂开。排查发现微信的 Referer 是 https://mp.weixin.qq.com/,不在白名单。加上 *.weixin.qq.com 后解决。社会化分享平台(微信、微博、QQ、知乎)都要加白。
  5. if ($invalid_referer) 里的 rewrite 死循环:rewrite ^/.*$ /no-hotlink.png 会再次匹配到同一个 location。必须加 break,或者把占位图放到不被保护的路径。
  6. CDN 缓存了 403 响应:如果 CDN 把 403 也缓存了,白名单调整后要刷新 CDN。
  7. RSS 阅读器 / 邮件订阅里的图片:这些场景通常无 Referer,放行 none 即可覆盖。

总结

防盗链的落地顺序:先用 CDN 控制台的 Referer 白名单(最省事、拦在边缘),必勾”允许空 Referer”,把搜索引擎和社交平台域名加白;源站 Nginx 的 valid_referers 作为第二道防线;图片真正值钱再上 URL 签名鉴权。记住 Referer 防盗链只能防君子,图片上打水印(品牌露出)才是长期有效的手段。防盗链省下的流量费,配合 WordPress CDN 回源配置与缓存规则 的命中率优化,能把 CDN 账单压下一大截。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。