nginx作为边缘网关应统一处理301重定向,仅在http server块中用return 301实现https强制跳转等全局策略;后端服务返回的302/301需由proxy_redirect修正,禁止在upstream或location中使用return 301干扰代理链路。

在分布式微服务架构中,Nginx 作为边缘网关统一处理 301 重定向,关键不在于“每个服务自己跳”,而在于把跳转逻辑收束到最外层、且与部署拓扑严格对齐。跳转位置、判断依据、目标地址三者必须协同,否则容易出现循环跳转、路径丢失或暴露内网地址等问题。
明确 Nginx 的角色:它只做边缘入口跳转,不做服务内跳转
微服务内部(如 Spring Boot 应用)产生的 302/301 响应(例如登录重定向、权限校验跳转),默认会返回原始 Location 头(如 /login 或 http://user-svc:8080/login)。这类响应应由 proxy_redirect 指令修正,而不是靠 return 301 二次干预。真正的 HTTPS 强制跳转、域名归一化等全局策略,才应在 Nginx 的 HTTP server 块中用 return 301 统一出口。
- HTTP → HTTPS 跳转只在最外层 Nginx 入口配置,后端服务无需感知协议
- 所有微服务的
server_name、redirect_uri都应配置为公网可访问的统一域名(如https://api.example.com),避免生成内部地址 - 禁止在 upstream 或 backend location 块里写
return 301,这会干扰代理链路,破坏路径前缀语义
根据实际入口类型选择跳转判断方式
不能写死 return 301 https://$host$request_uri——$host 易被恶意构造,$server_name 又无法适配多域名场景。正确做法是结合部署环境动态判断原始协议:
-
直连客户端(裸机/Nginx 独立部署):用
$scheme判断,配置if ($scheme = http) { return 301 https://$server_name$request_uri; } -
前置 Azure / AWS ALB / 阿里云 SLB 等负载均衡器:依赖
$http_x_forwarded_proto,且跳转目标必须写死公网域名,如https://api.example.com$request_uri -
Kubernetes Ingress 场景:关闭 Nginx 自定义跳转,改用 Ingress Controller 注解,例如
nginx.ingress.kubernetes.io/ssl-redirect: "true",由控制器注入标准跳转逻辑
路径前缀类服务需同步修正后端重定向响应
当 Nginx 以路径路由方式接入微服务(如 location /user/ { proxy_pass http://user-svc/; }),而后端返回 Location: /login,浏览器会跳到 https://example.com/login,而非预期的 https://example.com/user/login。此时必须用 proxy_redirect 重写响应头:
- 添加
proxy_redirect http://user-svc/ /user/;修正绝对地址 - 添加
proxy_redirect / /user/;修正相对地址(常见于 Spring Security) - 若后端返回带协议的 Location(如
http://user-svc/login),还需配合proxy_set_header Host $host;和proxy_redirect http:// /;配合清理
避免 Host 注入与域名硬编码冲突
所有跳转目标中的域名都应来自可信来源,禁用 $host 直接拼接。推荐两种安全写法:
- 使用
$server_name(仅适用于单域名、且已在 server 块中明确定义) - 显式写死可信域名(如
https://api.example.com$request_uri),并在 CI/CD 中通过变量注入,确保不同环境(staging/prod)自动切换 - 配合
underscores_in_headers on;和严格校验X-Forwarded-Host(如需支持多租户子域名),但生产环境建议直接禁用该头,由网关统一分发











