nginx通过error_page拦截后端返回的401/403状态码并重定向到自定义页面,需开启proxy_intercept_errors、配置=302跳转、单独设置错误页location并确保文件可读;授权判定必须由后端完成。

授权失败后的自动跳转,Nginx 本身不执行业务级鉴权(比如检查 token 是否有效、用户是否有权限),它只负责转发、重定向或拦截。真正的“授权失败”判断必须由后端服务(如 Spring Boot、Node.js、PHP)完成,Nginx 的作用是配合这个过程,实现干净、安全、可预期的跳转行为。
明确授权失败由谁判定
这是关键前提:Nginx 默认不会读取 Cookie、解析 JWT 或查数据库。它看到的只是 HTTP 请求头和路径。所以:
- 如果授权逻辑在后端(最常见),后端在检测失败后返回标准状态码(如 401 Unauthorized 或 403 Forbidden),再由 Nginx 拦截并跳转
- 如果使用 Nginx 的 auth_request 模块(需额外配置验证服务),Nginx 才会在代理前发起一次子请求校验,失败时直接返回 401/403 —— 此时跳转才真正由 Nginx 驱动
用 error_page 拦截并跳转
这是最常用、最可靠的方式。后端返回 401 或 403 后,Nginx 可捕获并重定向到登录页或提示页:
- 配置示例(跳转到同域登录页):
error_page 401 =302 /login?redirect=$request_uri;<br>error_page 403 =302 /forbidden;
-
=302表示保持原状态码语义但强制返回 302,避免浏览器缓存错误响应 -
$request_uri保留原始请求路径,供登录成功后回跳 - 确保
/login路径本身不受鉴权保护,否则会陷入死循环
配合反向代理透传关键头信息
若后端依赖 Host、协议或原始 IP 做授权决策(例如校验 Referer、生成安全跳转链接),Nginx 必须正确传递:
-
proxy_set_header Host $http_host;—— 防止后端误用 upstream 地址作为来源 -
proxy_set_header X-Forwarded-Proto $scheme;—— 让后端知道是 https 还是 http,避免生成 http:// 登录链接 -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;—— 便于后端记录真实客户端 IP - 避免写
proxy_set_header Host backend.example.com;这类硬编码,会覆盖原始 Host
避免跳转失效的典型陷阱
看似配置了 error_page,但跳转没生效?常见原因有:
- 后端返回的是 200 + 自定义错误体(如 { "code": 401 }),而非真实 HTTP 状态码 —— Nginx 不会拦截,必须让后端返回标准状态码
- 多个
error_page定义嵌套冲突(如 server 块和 location 块里都写了 401),内层 location 的优先级更高,可能覆盖外层设置 - 启用了
underscores_in_headers on;,而自定义 header(如 X-Auth-Result)含下划线,导致整个 header 解析被 Nginx 忽略,间接影响鉴权结果传递 - 跳转目标路径(如 /login)被 location 规则误匹配并 proxy_pass 到后端,造成二次鉴权失败











