Nginx中实现“防盗链+允许特定IP直连”的关键在于:用$allow_access变量综合判断referer合法性或IP是否在白名单,再通过return 403拦截未授权请求;需配合geo预处理IP、valid_referers设内置变量,并仅对静态资源location生效。
在 Nginx 中实现“防盗链 + 允许特定 IP 直接访问”,本质是:对 referer 做限制,但对指定 IP 地址豁免该限制。不能只靠 valid_referers,必须结合 if 和 $remote_addr 判断,再用变量控制是否放行。
先定义一个默认为拒绝的变量(如 $allow_access),然后根据条件(referer 合法 或 IP 在白名单)将其设为 1;最后在 location 中用 deny/allow 或返回状态码控制访问。
以下配置放在 server 或 location 块中:
# 定义白名单 IP(支持多个,用空格分隔)geo $white_ip {default 0;192.168.1.100 1;203.0.113.45 1;2001:db8::1 1; # 支持 IPv6}初始化访问权限变量set $allow_access 0;
如果是白名单 IP,直接允许if ($white_ip) { set $allow_access 1; }
如果 referer 合法(例如本站域名或空 referer),也允许valid_referers none blocked server_names *.example.com example.com; if ($valid_referers) { set $allow_access 1; }
拒绝未被允许的请求(例如返回 403)if ($allow_access = 0) { return 403; }
allow/deny 不能放在 if 块里,否则会报错或行为异常;改用 return 403 或 rewrite ... break 更可靠。$valid_referers,后续才能在 if 中判断。geo 预处理可避免重复字符串匹配。valid_referers 包含 none。把上述逻辑放在针对静态资源的 location 中,避免影响 API 或后台接口:
location ~* .(jpg|jpeg|png|gif|webp|pdf|zip|mp4)$ {# 上述 $allow_access 判断逻辑放在这里geo $white_ip { ... }set $allow_access 0;if (...) { ... }if ($allow_access = 0) {return 403;}}