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

.NET 6 ASP.NET Core中AzureAD Post认证与URLRewriting中间件故障修复

远程登录随机故障排查方案

问题概述

  • 生产/预发布环境随机触发错误:处理远程登录时遇到错误
  • 开发环境无此问题,调整中间件顺序后仍无法在开发环境复现
  • 无法直接访问生产/预发布环境

错误信息

处理远程登录时遇到错误。

堆栈跟踪

at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync() at 
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at 
Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at 
Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at 
Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) at Program.<>c.<<$>b__0_3>d.MoveNext() in D:\AzureDevOpsBuildAgent\_work\986\s\ApplicationName\Program.cs:line 65 --- End of stack trace from previous location --- at 
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)

当前中间件配置

var rewriteOptions = new RewriteOptions()
    .AddRewrite(@"^(?!controller1|controller2|controller3)(\w+)/?$", "Controller2/Index?Id=$1", skipRemainingRules: true);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var localzationOptions = services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value;
    app.UseRequestLocalization(localzationOptions);
}
app.UseSystemWebAdapters();
app.UseRewriter(rewriteOptions);
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Controller2}/{action=Index}/{id?}");
});

排查与修复建议

1. 修正中间件顺序(核心问题)

从堆栈跟踪和当前配置看,存在两个关键顺序问题:

  • 认证中间件缺失显式注册:远程认证(如OAuth/OpenID Connect)需要调用app.UseAuthentication(),且必须放在UseRouting()之后、UseAuthorization()之前
  • 重写中间件位置错误:UseRewriter()在认证前执行,可能篡改远程登录的回调URL,导致认证流程失败
  • Session中间件重复调用:堆栈中出现两次SessionMiddleware.Invoke,需确认是否重复注册

调整后的推荐顺序:

var rewriteOptions = new RewriteOptions()
    .AddRewrite(@"^(?!controller1|controller2|controller3)(\w+)/?$", "Controller2/Index?Id=$1", skipRemainingRules: true);
app.UseHttpsRedirection();
app.UseStaticFiles();
// 确保只注册一次UseSession()
app.UseSession();
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var localzationOptions = services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value;
    app.UseRequestLocalization(localzationOptions);
}
app.UseSystemWebAdapters();
app.UseRouting();
// 显式注册认证中间件,必须在UseAuthorization之前
app.UseAuthentication();
app.UseAuthorization();
// 将重写移到认证之后,避免影响登录回调
app.UseRewriter(rewriteOptions);
app.UseEndpoints(endpoints => {
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Controller2}/{action=Index}/{id?}");
});

2. 排查Session异常重复调用

堆栈中两次出现SessionMiddleware.Invoke,可能的原因:

  • 代码中重复调用了app.UseSession()
  • NuGet包版本冲突导致中间件被自动重复添加
    要求运维团队检查生产环境的启动日志,确认Session中间件的注册次数

3. 收集生产环境详细日志

请运维团队配合:

  • 在appsettings.json中开启认证模块的Debug级日志:
    "Logging": {
      "LogLevel": {
        "Microsoft.AspNetCore.Authentication": "Debug"
      }
    }
    
  • 捕获远程认证的具体错误细节(如状态参数验证失败、回调URL不匹配、Session过期等)
  • 检查分布式缓存(如Redis/SQL Server)的连接状态,生产环境Session通常依赖分布式缓存,而开发环境用内存缓存,这是核心差异点

4. 模拟生产环境配置复现问题

在开发环境中模拟生产环境的关键配置:

  • 配置分布式缓存(如Redis)替代内存缓存存储Session
  • 将Session过期时间调整为生产环境的设置
  • 测试登录后长时间闲置再操作的场景,排查Session超时引发的认证失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:00:40