为何仅在IMiddleware中User.Identity.IsAuthenticated始终为false?
问题原因分析
这一现象的核心在于ASP.NET Core的认证与授权触发机制,以及中间件执行顺序的影响:
授权驱动认证
UseAuthorization()中间件仅在请求需要授权(如接口标记[Authorize]特性、配置全局授权策略)时,才会强制触发认证流程,将请求携带的认证Cookie解析为HttpContext.User。而Swagger页面(swagger/index.html)属于默认匿名可访问的资源,UseAuthorization()不会触发认证逻辑,因此HttpContext.User始终处于未认证状态。SAML认证中间件的执行逻辑
你使用的UseSaml2()中间件默认不会主动为所有请求解析认证Cookie,而是依赖UseAuthorization()的触发信号来执行认证操作。对于无需授权的Swagger请求,认证中间件不会启动解析流程,自然无法识别携带的Cookie。中间件顺序的影响
自定义的SwaggerAuthMiddleware位于UseAuthorization()之后:- 针对需要授权的接口请求,
UseAuthorization()已经完成认证流程,HttpContext.User被填充为已认证状态; - 针对Swagger请求,
UseAuthorization()未触发认证,User状态保持未认证。
- 针对需要授权的接口请求,
解决方法
如果需要让Swagger请求也能获取认证状态,可通过以下两种方式实现:
方式一:在自定义中间件中手动触发认证
针对Swagger路径主动调用认证逻辑,强制解析Cookie:
public class SwaggerAuthMiddleware : IMiddleware { public async Task InvokeAsync(HttpContext context, RequestDelegate next) { // 仅对Swagger路径触发认证 if (context.Request.Path.StartsWithSegments("/swagger")) { // 替换为你的SAML认证方案名称(通常为"Saml2") var authResult = await context.AuthenticateAsync("Saml2"); if (authResult.Succeeded) { context.User = authResult.Principal; } } var isAuthenticated = context.User.Identity.IsAuthenticated; await next.Invoke(context); var isAuthenticated2 = context.User.Identity.IsAuthenticated; var stopper = 1; } }
方式二:配置全局授权+Swagger匿名豁免
通过全局授权策略强制所有请求走认证流程,再单独允许Swagger路径匿名访问:
- 配置全局授权策略:
services.AddAuthorization(options => { // 设置默认授权策略,要求所有请求必须认证 options.FallbackPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); });
- 为Swagger路径添加匿名访问豁免:
// 调整中间件映射,确保Swagger路径经过认证流程 app.MapWhen(context => context.Request.Path.StartsWithSegments("/swagger"), swaggerApp => { swaggerApp.UseAuthorization(); swaggerApp.UseSwagger(); swaggerApp.UseSwaggerUI(options => { options.RoutePrefix = "swagger"; options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyApplication"); }); }); // 其他路由映射 app.MapControllers();
内容的提问来源于stack exchange,提问作者ruddnisrus
相关产品推荐
相关产品推荐

