nginx可通过error_page 401 = @login统一拦截后端401并重定向至登录页,@login内用return 302跳转,保留原始uri供回跳,需区分auth_request与后端401的作用域配置。

不需要让每个后端服务自己处理 401,Nginx 可以统一拦截并跳转到登录页——关键是把 401 响应从后端“捕获”过来,再由 Nginx 主动重定向,而不是直接透传给用户。
拦截后端返回的 401
默认情况下,Nginx 会原样透传后端返回的 401。要统一接管,需用 error_page 指令捕获该状态码:
- 在 location 块中添加 error_page 401 = @login,表示遇到后端返回的 401 时,不直接返回给客户端,而是内部跳转到命名 location @login
- 确保该 location 位于 server 或 upstream 所在作用域内,且未被更细粒度的 error_page 覆盖
- 如果后端使用 JSON 返回 401(如
{"code":401,"msg":"Unauthorized"}),Nginx 仍能识别 HTTP 状态码,无需解析响应体
定义跳转逻辑 @login
@login 是一个内部命名 location,负责构造重定向响应:
- 用 return 302 发起跳转,例如:
return 302 https://sso.example.com/login?rd=$scheme://$host$request_uri; - $request_uri 保留原始请求路径,供登录成功后回跳;建议 URL 编码处理(可通过 Lua 或认证服务完成,Nginx 原生不自动编码)
- 避免使用 proxy_pass 到登录页——这会让登录页变成代理响应,失去浏览器地址栏跳转效果
区分后端 401 和 auth_request 401
auth_request 触发的 401(如认证服务拒绝)和后端返回的 401 是两类场景,需分开配置:
- auth_request 的 401 默认由 error_page 401 = @login 处理(常见于保护路径开头)
- 后端返回的 401 需显式声明在 proxy_pass 所在 location 中,例如:
location /api/ { proxy_pass http://backend; error_page 401 = @login; } - 若两者共存,注意 error_page 作用域层级,避免高优先级 location 中的设置被低优先级覆盖
可选:透传原始 401 原因(便于调试)
有时需要知道后端为何返回 401,可在 proxy_pass 后加 header 透传:
- proxy_hide_header WWW-Authenticate(可选):防止后端带出的 WWW-Authenticate 干扰前端逻辑
- proxy_pass_request_headers on(默认开启):确保 Authorization 等头被转发,方便后端鉴权
- 通过日志记录 $upstream_http_www_authenticate 或 $upstream_status,辅助定位是 token 过期还是权限不足











