You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 4身份认证跳转登录在YARP+Nginx代理下异常

问题描述

在Azure环境中部署了基础配置的YARP反向代理,请求会先转发至运行ModSecurity规则校验的Nginx反向代理容器,再传递至后端Web应用。引入YARP的目的是提供公网静态IP,使Nginx容器及其挂载资源可安全部署于无公网IP的虚拟网络中。

该Web应用是基于.NET 4的传统WebForms应用,集成了ASP.NET Identity。除直接访问需授权页面的场景外,其余功能均正常:正常流程应为跳转至登录页,验证后返回原受限页面,但实际访问https://targethost.com/restrictedpage时,被重定向至https://nginxhost.com/login.aspx?returnUrl=/restrictedpage,而非预期的https://targethost.com/login.aspx?returnUrl=/restrictedpage。若先访问https://targethost.com/login.aspx完成登录,则可正常访问受限页面。

相关配置

YARP路由配置

"AllowedHosts": "*",
  "ReverseProxy": {
    "Routes": {
      "route1": {
        "ClusterId": "cluster1",
        "Match": {
          "Path": "{**catch-all}",
          "Hosts": [ "targethost.com" ]
        },
      }
    },
    "Clusters": {
      "cluster1": {
        "Destinations": {
          "destination1": {
            "Address": "http://nginxproxy.com:80/"
          }
        }
      }
    }
  }

Nginx代理配置

server {
    listen 80 default_server;

    server_name nginxproxy.com;
    set $upstream https://webapp.com;
    set $always_redirect off;

    location / { ...
       proxy_set_header Host $host;    
       proxy_set_header Proxy "";
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection $connection_upgrade;
       proxy_set_header X-REAL-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Port $server_port;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_redirect off;

       proxy_pass_header Authorization;
       proxy_pass $upstream;

       set_real_ip_from 10.5.3.254;
       set_real_ip_from 127.0.0.1;

       real_ip_header X-REAL-IP;
       real_ip_recursive on;.
}

Web应用身份认证配置

app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
    .ExpireTimeSpan = TimeSpan.FromMinutes(5),
    .SlidingExpiration = True,
    .AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    .Provider = New CookieAuthenticationProvider() With {
        .OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser)(
            validateInterval:=TimeSpan.FromMinutes(30),
            regenerateIdentity:=Function(manager, user) user.GenerateUserIdentityAsync(manager))},
    .LoginPath = New PathString("/Account/Login")})

更新补充:OWIN中间件配置

Public Sub Configuration(app As IAppBuilder)
Dim c = New CookieAuthenticationOptions
c.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
c.LoginPath = New PathString("/account/login")
app.UseCookieAuthentication(c)

根据文档说明:LoginPath属性用于处理ChallengeAsync时的重定向目标,当前URL会以ReturnUrlParameter指定的查询参数附加至LoginPath,登录成功后会据此跳转回原URL。


原因分析

核心问题是后端Web应用生成重定向URL时,使用了Nginx传递的Host头值(nginxproxy.com),而非用户实际访问的公网域名targethost.com:

  • Nginx配置中proxy_set_header Host $host;的$host变量会取Nginx自身的server_name值(即nginxproxy.com),导致后端Web应用误以为当前请求的主机是nginxproxy.com,生成登录跳转URL时就用了这个域名。
  • .NET 4的ASP.NET Identity在处理未授权请求的重定向时,会基于当前请求的Host头拼接完整的登录URL,未正确识别反向代理传递的原始请求域名。

修复方案

方案1:修改Nginx配置,传递原始请求Host头

将Nginx配置中的proxy_set_header Host $host;替换为以下两种方式之一:

  • 方式A:保留客户端原始Host头
    proxy_set_header Host $http_host;
    
  • 方式B:固定为公网目标域名(仅适用于单一域名场景)
    proxy_set_header Host targethost.com;
    

修改后的完整Nginx location片段:

location / { ...
   proxy_set_header Host $http_host;    
   # 或者使用固定域名:proxy_set_header Host targethost.com;
   proxy_set_header Proxy "";
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection $connection_upgrade;
   proxy_set_header X-REAL-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Port $server_port;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_redirect off;

   proxy_pass_header Authorization;
   proxy_pass $upstream;

   set_real_ip_from 10.5.3.254;
   set_real_ip_from 127.0.0.1;

   real_ip_header X-REAL-IP;
   real_ip_recursive on;.
}

说明:$http_host会保留客户端请求时的原始Host头(即targethost.com),后端Web应用就能基于正确的域名生成登录跳转URL。

方案2:修改Web应用代码,拦截并重写重定向URL

若无法修改Nginx配置,可通过OWIN中间件拦截默认的重定向逻辑,手动替换域名:

Public Sub Configuration(app As IAppBuilder)
    Dim c = New CookieAuthenticationOptions
    c.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
    c.LoginPath = New PathString("/account/login")
    ' 拦截重定向逻辑,替换域名
    c.Provider = New CookieAuthenticationProvider() With {
        .ApplyRedirect = Function(context)
            Dim redirectUrl = context.RedirectUri
            ' 将错误域名替换为公网目标域名
            redirectUrl = redirectUrl.Replace("https://nginxproxy.com", "https://targethost.com")
            context.Response.Redirect(redirectUrl)
        End Function
    }
    app.UseCookieAuthentication(c)
End Sub

说明:通过ApplyRedirect方法覆盖默认重定向行为,将生成的URL中的nginxproxy.com替换为targethost.com,确保跳转目标正确。

额外优化:配置Forwarded Headers

为确保Web应用正确识别原始请求的协议和客户端信息,可添加OWIN的UseForwardedHeaders中间件:

app.UseForwardedHeaders(New ForwardedHeadersOptions() With {
    .ForwardedHeaders = ForwardedHeaders.XForwardedFor Or ForwardedHeaders.XForwardedProto
})

说明:该配置让应用信任反向代理传递的X-Forwarded-*头,有助于生成正确的HTTPS URL及获取真实客户端IP。


内容的提问来源于stack exchange,提问作者ibeme99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 16:35:54