Nginx反向代理中需拦截后端401响应、清除WWW-Authenticate头并重定向至登录页:用proxy_hide_header WWW-Authenticate隐藏头,error_page 401 = @login捕获,location @login中return 302跳转且携带原始URI。

在 Nginx 反向代理中,后端返回的 401 Unauthorized 响应通常附带 WWW-Authenticate 头(如 Bearer realm="api"),但这个头默认会透传给客户端——这在 Web 应用中往往不必要,甚至可能干扰前端逻辑或暴露认证细节。Nginx 的目标不是展示挑战头,而是统一接管 401 并跳转到登录页。关键在于“拦截 + 清除 + 重定向”,而非透传或解析。
拦截后端 401 并阻止透传 WWW-Authenticate
默认情况下,Nginx 会原样转发后端的 401 和所有响应头(包括 WWW-Authenticate)。要避免前端收到该头,需显式隐藏:
- 在 proxy_pass 所在的
location中添加:proxy_hide_header WWW-Authenticate; - 确保该指令位于
proxy_pass之前,且未被更内层配置覆盖 - 若需调试原因(如区分 token 过期 vs 权限不足),可临时记录:
log_format main ... $upstream_http_www_authenticate;
用 error_page 捕获并重定向,而非透传 401
仅隐藏头还不够;必须让 Nginx 主动终止透传流程,改走自定义跳转逻辑:
- 在对应 location 中添加:
error_page 401 = @login; - 定义内部命名 location:
location @login { return 302 /login?rd=$scheme://$host$request_uri; } - 务必确认
/login路径本身不受auth_request或其他鉴权保护,否则会死循环 - 不要用
proxy_pass到登录页——那会导致浏览器地址栏不变,失去“跳转”语义
注意 auth_request 触发的 401 不在此列
auth_request 子请求失败产生的 401 是 Nginx 自主生成的,它不来自后端,也不带 WWW-Authenticate 头。这类 401 需单独处理:
- 它默认由 server 级或 location 级的
error_page 401 = @login拦截(与后端 401 共享同一跳转逻辑) - 但若你同时存在后端 401 和
auth_request401,需确保error_page作用域不被覆盖:例如,在/api/location 中声明error_page 401 = @login,就只影响该路径下的后端响应,不影响根路径的auth_request行为
补充:保留原始请求上下文供回跳
跳转时携带原始 URI 是关键体验点:
- 使用
$request_uri(含 query string)比$uri更完整 - Nginx 原生不自动 URL 编码,若 URI 含特殊字符(如
&、=),建议由登录服务解码,或通过 Lua 模块预处理 - 也可用
$scheme://$host$request_uri构造绝对 URL,避免协议/域名丢失


















