.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
相关产品推荐
相关产品推荐

