nginx防盗链应使用if + return判断$http_referer,限定在图片等资源location块内,显式处理空referer,并优先选用valid_referers指令替代手工正则匹配。

利用 if 和 return 实现防盗链,核心是在 Nginx 配置中判断请求头 Referer 是否来自允许的域名,不满足条件时直接用 return 中断响应(如返回 403 或重定向到默认图)。
检查 Referer 并拒绝非法来源
Nginx 不支持在 if 中直接执行复杂逻辑,但可以结合 if + return 做基础防盗链控制。关键点是:if 只能用于 server 或 location 块内,且仅支持有限变量(如 $http_referer)。
- 用
if ($http_referer !~ ^https?://(www\.)?yourdomain\.com/)匹配非本站来源 - 匹配成功后立即
return 403或return 302 /static/forbidden.png - 注意:空 Referer(如直接访问图片 URL、HTTPS 页面引用 HTTP 资源)默认被拒绝,需显式放行:
if ($http_referer ~ ^$) { return 403; }或改为return 200;若需允许
只对特定资源启用防盗链
避免误伤 API 或静态资源,应把规则限定在图片、视频等易被盗用的文件类型上:
- 写在
location ~*\.(jpg|jpeg|png|gif|webp|mp4|pdf)$ { ... }块内 - 这样 CSS、JS、HTML 或接口路径不受影响
- 若需放行搜索引擎(如百度、Google),可追加多条件:
if ($http_referer !~ ^https?://(www\.)?(yourdomain\.com|baidu\.com|google\.com)/) { return 403; }
注意 if 的限制和常见坑
if 在 Nginx 中是“伪指令”,行为与编程语言不同:它不是条件分支,而是每次请求都求值,且嵌套或复杂逻辑易出错。
- 不能在
if内写多个指令(如set + return),除非用rewrite ... break替代 -
if不支持&&/||,多条件要用正则组合,例如:!~ ^(https?://)?(www\.)?yourdomain\.com - HTTPS 站点引用 HTTP 图片会触发 Referer 被浏览器清空,导致误判——建议全站 HTTPS 并用
Referrer-Policy: no-referrer-when-downgrade
更健壮的替代方案(进阶参考)
若业务要求高可靠性,建议用 valid_referers 指令替代手工 if:
valid_referers none blocked server_names *.yourdomain.com;if ($invalid_referer) { return 403; }- 它自动处理空 Referer、加密降级、协议差异等边界情况,语义更清晰,也更少出错











