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

SystemWeb Adapters认证因多重重定向导致URL过长失败

问题

在使用SystemWeb Adapters和YARP从.NET 4.8 ASP.NET增量迁移至ASP.NET Core 8.0时,遇到认证循环重定向问题:未登录状态下用移动端访问首页,ReturnUrl被递归嵌套添加到请求URL中,导致URL超长(示例URL已省略重复部分)。

ASP.NET Core端代码

using WebCore;
using Yarp.ReverseProxy.Forwarder;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddSystemWebAdapters()
    .AddJsonSessionSerializer(options =>
    {
        // <snip>
    })
    .AddRemoteAppClient( options =>
    {
        options.RemoteAppUrl = new(builder.Configuration["ProxyTo"]);
        options.ApiKey = builder.Configuration["ProxyApiKey"];
    })
    .AddAuthenticationClient(isDefaultScheme: true)
    .AddSessionClient();

builder.Services.AddHttpForwarder();
builder.Services.AddDetection();

builder.Services.AddWebOptimizer(//<snip>);

// <snip>

var app = builder.Build();

var forwarderRequestConfig = builder.Configuration.GetSection("ForwarderRequestConfig")
    .Get<ForwarderRequestConfig>();

if (!app.Environment.IsDevelopment())
{
    app.UseHsts();
}

app.UseCors();

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseAuthorization();
app.UseSystemWebAdapters();

app.MapForwarder("/{**catch-all}", app.Configuration["ProxyTo"], forwarderRequestConfig, new ForwardOriginalUrlTransformer())
    .Add(static builder => ((RouteEndpointBuilder)builder).Order = int.MaxValue);

app.MapDefaultControllerRoute()
    .RequireSystemWebAdapterSession();

app.Run();

ASP.NET端AccountsController的Login方法

[Mobility]
public ActionResult Login(string returnUrl = "", string mode = "")
{
    SecurityService.Logout();

    if (returnUrl.Contains("/account/login"))
        return RedirectToAction("login", "account", new { mode = "login" });

    var model = new
                {
                    Mode = mode,
                    RedirectUrl = returnUrl,
                    ValidationLiterals = AccountFacade.ValidationLiterals()
                };

    return View(model.ToJson());
}

Mobility属性代码

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    // Determine if we've processed their preference already via the UI site-switching links
    var useMobileValue = HttpContext.Current.Session["UseMobile"];

    bool useMobile;
    // <snip>

    if (useMobile)
    {
        var url = "/mobile";

        if (!Global.Authenticated)
            url += "/login";

        filterContext.Result = new RedirectResult(url);
    }
}

当前疑问:多重重定向是否会影响认证流程?有无可行解决办法?若将首页和Accounts控制器迁移至ASP.NET Core,该如何设置登录路径?


解决方案

问题根源

未登录移动端访问首页时,Mobility属性重定向到/mobile/login,该请求被YARP转发至旧ASP.NET应用;旧应用的Login方法检测到ReturnUrl包含/account/login会再次重定向,同时SystemWeb Adapters的认证客户端自动添加/systemweb-adapters/authenticate和original-url参数,形成循环重定向,导致ReturnUrl不断嵌套。

多重重定向会触发浏览器URL长度限制,增加服务器负载,直接中断正常认证流程,必须打破循环才能解决。

临时修复(不迁移控制器)

  1. 调整Mobility属性重定向逻辑:直接重定向到移动端登录页,避免携带可能引发循环的ReturnUrl
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var useMobileValue = HttpContext.Current.Session["UseMobile"];
    bool useMobile;
    // <snip>

    if (useMobile)
    {
        var url = "/mobile/login";
        // 直接重定向,不携带当前请求的returnUrl
        filterContext.Result = new RedirectResult(url);
    }
}
  1. 修改旧Login方法的循环判断逻辑:精准识别循环路径,直接返回视图而非重定向
[Mobility]
public ActionResult Login(string returnUrl = "", string mode = "")
{
    SecurityService.Logout();

    var loopPaths = new[] { "/account/login", "/mobile/login" };
    if (!string.IsNullOrEmpty(returnUrl) && loopPaths.Any(p => returnUrl.Contains(p, StringComparison.OrdinalIgnoreCase)))
    {
        var model = new
        {
            Mode = mode,
            RedirectUrl = "", // 清空循环的ReturnUrl
            ValidationLiterals = AccountFacade.ValidationLiterals()
        };
        return View(model.ToJson());
    }

    var model = new
    {
        Mode = mode,
        RedirectUrl = returnUrl,
        ValidationLiterals = AccountFacade.ValidationLiterals()
    };

    return View(model.ToJson());
}

迁移首页和Accounts控制器至ASP.NET Core的配置

  1. 配置认证与会话同步
// Program.cs 服务配置部分
builder.Services.AddAuthentication(SystemWebAdaptersAuthenticationDefaults.AuthenticationScheme)
    .AddSystemWebAdaptersAuthentication();

builder.Services.AddSystemWebAdapters()
    .AddJsonSessionSerializer(options =>
    {
        // <snip>
    })
    .AddRemoteAppClient(options =>
    {
        options.RemoteAppUrl = new(builder.Configuration["ProxyTo"]);
        options.ApiKey = builder.Configuration["ProxyApiKey"];
    })
    .AddSessionClient();
  1. 调整中间件顺序
// Program.cs 管道配置部分
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSystemWebAdapters();
  1. 映射登录路由与授权策略
// 映射移动端登录路由
app.MapControllerRoute(
    name: "MobileLogin",
    pattern: "/mobile/login",
    defaults: new { controller = "Account", action = "MobileLogin" });

// 默认路由需授权
app.MapControllerRoute(
    name: "Default",
    pattern: "{controller=Home}/{action=Index}/{id?}")
    .RequireAuthorization();
  1. 编写ASP.NET Core端Account控制器
public class AccountController : Controller
{
    public IActionResult Login(string returnUrl = "")
    {
        if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
        {
            ViewData["ReturnUrl"] = returnUrl;
        }
        return View();
    }

    public IActionResult MobileLogin(string returnUrl = "")
    {
        // 复用Login视图,传递ReturnUrl
        ViewData["ReturnUrl"] = returnUrl;
        return View("Login");
    }

    [HttpPost]
    public async Task<IActionResult> Login(LoginModel model, string returnUrl = "")
    {
        // 实现认证逻辑(可调用旧应用认证接口或通过SystemWeb Adapters同步会话)
        
        // 认证成功后重定向到原路径
        if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
        {
            return Redirect(returnUrl);
        }
        return RedirectToAction("Index", "Home");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 21:38:10