Nginx auth_request配置:如何实现登录认证后跳转回原始请求地址
Nginx auth_request鉴权场景下登录后回跳原始路径实现方案
核心实现逻辑
auth_request触发401走自定义错误页时,Nginx请求上下文会全程保留用户最初发起的原始请求URI(含查询参数),不会被/access_token这类内部子请求、error_page内部跳转篡改。只要在跳转到登录页时把这个原始路径传递给登录服务,登录完成后读取该地址跳转即可实现自动回跳。
可落地方案
方案1:Cookie存储原始路径(零额外依赖,落地最快)
该方案不需要修改Nginx全局配置,不会出现参数拼接冲突问题,适配绝大多数生产场景:
- 在401跳转逻辑中,给用户写入一个临时HttpOnly Cookie存储原始访问路径,设置短有效期(足够完成登录操作即可),全站可读。
- 登录服务校验账号密码通过、下发认证凭证后,读取请求中携带的临时Cookie值,302跳转到对应原始路径,同时删除该临时Cookie。
替换原有配置中的@error401块即可:
location @error401 { # 写入临时Cookie:存原始路径、10分钟有效期、全站可读、禁止前端读取、Lax安全策略 add_header Set-Cookie "original_uri=$request_uri; Path=/; Max-Age=600; HttpOnly; SameSite=Lax"; return 302 '/login/'; }
登录服务端配套逻辑非常简单:
- 登录校验通过后,从Cookie中读取
original_uri字段值 - 若值存在且为站内合法路径,返回302跳转到该地址,同时通过Set-Cookie将
original_uri设置为过期(Max-Age=0)完成清理 - 若值不存在或非法,跳转到默认首页/用户中心即可
方案2:Query参数传递原始路径(兼容禁用Cookie场景)
如果需要兼容用户禁用Cookie的场景,可以把原始路径编码后作为URL参数拼接到登录页地址上,注意必须做URL编码,避免原始路径自带的查询参数和登录页参数冲突。
- OpenResty/Nginx 1.25+版本(内置URI编码能力)配置:
location @error401 { set $raw_redirect $request_uri; access_by_lua 'ngx.var.encoded_redirect = ngx.escape_uri(ngx.var.raw_redirect)'; return 302 /login/?redirect=$encoded_redirect; }
- 原生Nginx低版本兼容配置(利用内部rewrite自动编码能力):
location @error401 { rewrite ^ /_internal_encode?target=$request_uri? last; } location /_internal_encode { internal; if ($arg_target) { rewrite ^ /login/?redirect=$arg_target? redirect; } return 302 /login/; }
登录服务端配套逻辑:
- 登录校验通过后,读取URL中的
redirect参数并做URL解码 - 校验参数为站内合法路径后302跳转,非法则跳转到默认首页
配置避坑提醒
- 不要用
$request、$uri变量存储原始路径:$request是完整请求行,包含HTTP方法、协议版本,格式类似GET /secure HTTP/1.1,无法直接用于跳转;$uri会被内部重写、rewrite规则修改,拿到的不是用户最初访问的地址,必须使用$request_uri。 - 必须加跳转地址校验:不管用Cookie还是Query参数传递跳转地址,登录端一定要校验目标地址是站内相对路径(以单
/开头,排除//开头的跨域跳转、带http/https协议的第三方地址),避免出现开放重定向漏洞,被利用构造钓鱼链接。 - auth_request内部子请求不会修改
$request_uri的值,不需要担心子请求逻辑覆盖原始路径,该变量在整个请求生命周期内都对应用户最开始发起的请求地址。
内容的提问来源于stack exchange,提问作者Peter Jaffray
相关产品推荐
相关产品推荐

