跨域referer校验失败源于浏览器strict-origin-when-cross-origin策略与nginx valid_referers配置不匹配:跨域时仅发源站(如https://a.com),而配置若依赖完整url(如https://a.com/xxx)则必然失败;应改用none、blocked、server_names组合白名单,并避免对api盲目校验。

跨域请求时 Referer 校验冲突,本质是浏览器 Strict-Origin-When-Cross-Origin 策略与 Nginx valid_referers 配置不匹配导致的——不是配置错了,而是没对齐浏览器实际发什么。
理解浏览器跨域时到底发什么 Referer
现代浏览器默认使用 Strict-Origin-When-Cross-Origin 策略:
- 同源请求(如
https://a.com→https://a.com/api):发送完整 Referer(含路径、参数) - 跨域请求(如
https://a.com→https://api.b.com/user):只发送源(https://a.com),砍掉路径和查询参数 - 降级请求(HTTPS 页面请求 HTTP 资源):Referer 直接清空(变成空)
如果你在 Nginx 中写的是 valid_referers ~* https://a.com/xxx; 或依赖完整 URL 匹配,那跨域请求必然失败——因为浏览器根本没发 /xxx 这部分。
防盗链配置必须兼容跨域场景
针对图片等静态资源做 Referer 校验时,不能只认“完整 URL”,得覆盖三种合法来源状态:
- none:允许空 Referer(直接访问、HTTPS→HTTP 降级、书签打开)
-
blocked:允许被代理/CDN 截断后的 Referer(如只有
a.com没协议) -
server_names:用域名白名单,而非硬编码 URL;支持通配符,例如:
valid_referers none blocked server_names *.yourdomain.com yourdomain.com;
这样无论用户从同域页面跳转、跨域前端调用,还是小程序 WebView 加载,只要来源是你的域名体系,就不会被误拦。
避免对 API 接口盲目套用 Referer 校验
API 请求(尤其是前后端分离项目)天然常跨域,且:
- 移动端 App、微信小程序、桌面客户端根本不发 Referer
- fetch / axios 的跨域请求只带源,不带路径
- 管理后台类接口若确需校验,应限定在
location /admin/等明确 Web 端调用的路径,并配合日志观察$http_referer实际值
更稳妥的做法是:API 层用 Origin 校验(比 Referer 更可靠、不可被 JS 修改),或直接交由后端做 Token / CSRF Token 验证。
Vue/React SPA 布署下的特别注意点
单页应用使用 history 模式时,前端路由跳转不刷新页面,Referer 不变——这本身不是问题。但容易踩的坑是:
- 把防盗链规则写在
location /块里,干扰了try_files $uri $uri/ /index.html的 fallback 逻辑 - 对所有静态资源(包括
.js、.css)都加 Referer 校验,导致首屏加载失败(此时 Referer 为空或不可靠)
正确做法是:只对图片类资源(.png|.jpg|.webp)启用校验,且放在独立 location 块中,例如:
location ~* \.(png|jpe?g|gif|webp)$ {
valid_referers none blocked server_names *.example.com example.com;
if ($invalid_referer) { return 403; }
}
不复杂但容易忽略。











