← 返回题目列表

Nginx 如何解决跨域、防盗链和 URL 重写?

高频 中等 第 5 / 25 题 更新于 2026/07/28
Nginx跨域防盗链rewrite

简化版

跨域(CORS):浏览器同源策略限制跨域请求,Nginx 可通过 add_header 添加 Access-Control-Allow-Origin 等响应头,并处理 OPTIONS 预检请求,在网关层统一解决跨域。防盗链:防止别的网站直接引用你的图片/资源盗刷流量,用 valid_referers 检查请求来源 Referer,非法来源返回 403。URL 重写(rewrite):用 rewrite 指令按正则改写 URL,实现路径映射、跳转、伪静态等(rewrite 正则 替换 [flag],常用 flag 有 lastbreakredirectpermanent)。

详细版

① 跨域 CORS:

location /api/ {
    add_header Access-Control-Allow-Origin $http_origin;   # 允许的源
    add_header Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS";
    add_header Access-Control-Allow-Headers "Content-Type,Authorization";
    add_header Access-Control-Allow-Credentials true;
    if ($request_method = OPTIONS) {
        return 204;                    # 预检请求直接返回
    }
    proxy_pass http://backend;
}

② 防盗链:

location ~* \.(jpg|png|gif)$ {
    valid_referers none blocked server_names *.mysite.com;
    if ($invalid_referer) {
        return 403;                    # 非法来源拒绝
    }
}

③ URL 重写 rewrite:

rewrite ^/old/(.*)$ /new/$1 permanent;    # 301 永久重定向
rewrite ^/article/(\d+)$ /article.php?id=$1 last;   # 伪静态
  • rewrite flaglast(重写后重新匹配 location)、break(重写后停止)、redirect(302 临时)、permanent(301 永久)。

完整版教学

一、跨域 CORS:为什么以及怎么解决

同源策略是浏览器的安全机制:默认只允许网页向同源(协议、域名、端口都相同)的地址发请求,跨源(比如前端 a.com 访问接口 api.b.com)会被浏览器拦截。这就是跨域问题

CORS(跨域资源共享) 是标准的解决方案:服务端在响应里加特定的头,告诉浏览器「我允许这个源跨域访问我」,浏览器就放行。可以在后端加,也可以统一在 Nginx 层加(更集中、后端无需改代码):

  • Access-Control-Allow-Origin:允许哪个源跨域(* 允许所有,或指定具体域名;带凭证时不能用 *)。
  • Access-Control-Allow-Methods:允许的 HTTP 方法。
  • Access-Control-Allow-Headers:允许的自定义请求头。
  • Access-Control-Allow-Credentials:是否允许带 Cookie。

预检请求(OPTIONS):对于非简单请求(如带自定义头、PUT/DELETE),浏览器会先发一个 OPTIONS 请求探路(预检),确认服务端允许后才发真正的请求。Nginx 要专门处理 OPTIONS——直接返回 204 和 CORS 头,不用转发给后端。

二、防盗链:保护你的资源不被盗用

盗链指别的网站直接引用你服务器上的资源(尤其图片、视频、下载文件)。比如你网站的图片 mysite.com/img.jpg,被 other.com 直接 <img src="mysite.com/img.jpg"> 引用——用户访问 other.com 时,图片流量和带宽却由你的服务器承担,相当于被白嫖流量。

防盗链原理:利用 HTTP 请求头里的 Referer(记录请求是从哪个页面发起的)。正常情况下,加载你网站图片的请求,Referer 应该是你自己的域名;如果 Referer 是别的网站,就是盗链。

Nginx 用 valid_referers 配置合法来源:

  • valid_referers none blocked server_names *.mysite.com;——none(无 Referer,如直接访问)、blocked(Referer 被防火墙删除)、自己的域名都算合法。
  • 不在白名单的来源,$invalid_referer 变量为真,return 403 拒绝。

注意 Referer 可以伪造,所以防盗链只能防「普通盗链」,对刻意伪造 Referer 的防不住(要更强防护得用签名 URL、Token 等)。

三、URL 重写 rewrite:改写请求路径

rewrite正则表达式改写请求的 URL,用途很多:

  • 路径映射/迁移:老路径 /old/xxx 重写到新路径 /new/xxx
  • 伪静态:把动态 URL(/article.php?id=123)对外展示成静态样子(/article/123),对 SEO 和美观有好处。
  • 重定向跳转:HTTP 跳 HTTPS、旧域名跳新域名。

语法:rewrite 正则 替换内容 [flag]。正则里用 (...) 捕获、替换里用 $1$2 引用。

四、rewrite 的四个 flag(关键考点)

rewrite 末尾的 flag 决定重写后的行为,容易混淆:

  • last:重写 URL 后,用新 URL 重新发起一轮 location 匹配(重新走一遍 location 规则)。常用于需要重写后再匹配其他 location 的情况。
  • break:重写 URL 后,停止继续处理 rewrite,直接用当前 location 的配置处理新 URL(不再重新匹配 location)。
  • redirect:返回 302 临时重定向(浏览器地址栏变成新 URL,临时性,搜索引擎不转移权重)。
  • permanent:返回 301 永久重定向(永久性,搜索引擎会把权重转移到新 URL,SEO 友好)。

记忆lastbreak内部重写(URL 变了但浏览器地址栏不变,服务器内部转发);redirectpermanent外部重定向(返回 3xx,浏览器地址栏变化、会再发一次请求)。last 会重新匹配 location,break 不会。

五、rewrite 与 location 的配合

rewritelocation 经常配合,理解执行顺序:Nginx 先按 location 匹配,进入 location 后可能有 rewrite。last 会让重写后的 URL 跳出当前 location 重新匹配(可能进入另一个 location),break留在当前 location 继续处理。用错 flag 可能导致重写死循环或匹配不到预期 location,是常见坑。

六、常见误区与追问

考点正确口径
CORS通过响应头控制浏览器跨域读取权限
防盗链根据 Referer 等限制外站引用资源
Rewrite按规则重写 URI 或跳转
add_header Access-Control-Allow-Origin https://a.com;
valid_referers none blocked server_names *.example.com;
rewrite ^/old/(.*)$ /new/$1 permanent;

CORS 是浏览器安全策略,防盗链是资源访问控制,rewrite 是 URL 规则变换,三者别混。

  • 误区:CORS 是 Nginx 让请求能不能发出。 跨域请求可能已到服务器,浏览器根据响应头决定 JS 能不能读响应。
  • 误区:Referer 防盗链绝对可靠。 Referer 可能为空或被伪造,只适合作为基础防护,重要资源要签名 URL。
  • 误区:rewrite 和 proxy_pass 是一回事。 rewrite 改 URI 或返回跳转,proxy_pass 是把请求代理到上游。
  • 追问:带 Cookie 的 CORS 怎么配? 不能用通配 *,要指定 Origin,并允许 credentials。
  • 追问:防盗链误伤怎么处理? 允许空 Referer、白名单域名,并对客户端/APP 场景做签名兜底。
  • 追问:rewrite permanent 和 last 有什么区别? permanent 返回 301 给客户端,last 在服务端继续按新 URI 匹配。

七、加强记忆

Nginx 三个常见需求:① 跨域 CORS——用 add_headerAccess-Control-Allow-Origin/Methods/Headers/Credentials,并单独处理 OPTIONS 预检(返回 204),在网关层统一解决同源策略限制;② 防盗链——用 valid_referers 检查请求的 Referer 头,非法来源($invalid_referer)返回 403,防止资源被别站盗用流量(但 Referer 可伪造,只防普通盗链);③ URL 重写 rewrite——rewrite 正则 替换 [flag] 改写 URL 做路径映射/伪静态/跳转,四个 flag:last(重写后重新匹配 location)、break(重写后留在当前 location)、redirect(302 临时)、permanent(301 永久)。口诀:跨域加响应头处理预检、防盗链查 Referer、rewrite 记住 last/break 内部转、redirect/permanent 外部跳