.NET 8中HealthChecks.UI调用/health报Unauthorized问题排查
问题描述
原始问题
基于.NET 8.0构建的项目,使用Azure AD(Entra ID)做身份验证,站点需登录关联AAD的微软账号并具备对应权限,其他功能及/health端点权限均正常,但遇到以下异常:
website.com/health:可正常返回健康状态JSON,内容如下:{"status":"Healthy","totalDuration":"00:00:01.1584121","entries":{"sqlserver":{"data":{},"duration":"00:00:01.1117668","status":"Healthy","tags":[]}}}website.com/healthchecks-ui:界面能正常加载,但健康检查显示“unhealthy”,错误信息为:HTTP response is not in valid state (Unauthorized) when trying to get report from /health configured with name All Health Checks.
相关配置代码
服务注册
services.AddHealthChecks().AddSqlServer(Configuration.GetConnectionString("OpkCoreDatabaseProduction")); services.AddHealthChecksUI().AddInMemoryStorage();
端点注册
app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "areas", pattern: "{area}/{controller}/{action=Index}/{id?}"); endpoints.MapControllerRoute( name: "default", pattern: "{area=General}/{controller=Home}/{action=Index}/{id?}"); endpoints.MapGraphQL("/graphql"); endpoints.MapHealthChecks("/health", new HealthCheckOptions { ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, }).AllowAnonymous(); endpoints.MapHealthChecksUI().AllowAnonymous(); });
appsettings.json配置
"HealthChecksUI": { "HealthChecks": [ { "Name": "All Health Checks", "Uri": "/health" } ], "EvaluationTimeInSeconds": 5 }
身份验证配置
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));
已尝试的方案:
- 调整多种
AddAuthorization()和AllowAnonymous()配置,/health始终正常,但HealthChecks.UI授权失败 - 服务器调试无法复现本地情况,也无法调试问题类库
- 修改Uri为完整域名,无效
- 不想设置IIS允许匿名访问整个站点
疑问:是否遗漏了令牌请求头的配置环节?
更新内容
确认存在深层次身份验证问题,且与HealthChecks.UI项目无关:
搭建了简单测试控制器,本地运行可正常返回数据,但在QA服务器调试时,调用https://mywebsite.com/health明确返回Unauthorized。测试控制器代码:
public async Task<IActionResult> Index() { HealthCheckViewModel model = new(); using HttpClient client = new(); HttpResponseMessage response = await client.GetAsync($"https://mywebsite.com/health"); var testResponse = response.Content.ReadAsStringAsync().Result; return View(model); }
解决方案
1. 排查服务器端/health端点的匿名访问拦截
虽然代码中给/health添加了.AllowAnonymous(),但QA服务器可能存在额外的身份验证拦截:
- 检查IIS站点的身份验证设置:确保匿名身份验证已启用,同时禁用其他强制身份验证的模块(如Windows身份验证)
- 若使用反向代理(如Azure应用网关、NGINX),验证代理是否未额外添加规则拦截
/health请求
2. 配置HealthChecks.UI内部请求的身份凭证
HealthChecks.UI的后台收集器是服务器内部发起的请求,部署环境中可能缺少身份令牌导致拦截,可通过添加授权头解决:
services.AddHealthChecksUI(settings => { settings.AddHealthCheckEndpoint("All Health Checks", "/health") .WithHeader("Authorization", $"Bearer {GetAadClientCredentialToken()}"); }).AddInMemoryStorage();
GetAadClientCredentialToken()需实现基于AAD客户端凭据流获取令牌的逻辑(可借助Microsoft.Identity.Client库)
3. 验证服务器环回请求权限
QA服务器可能限制了本地回环请求:
- 检查防火墙设置,允许127.0.0.1、localhost的HTTP/HTTPS请求
- 若用HTTPS,确保服务器证书能被本地请求信任,避免SSL验证失败
4. 明确端点的匿名授权规则
调整/health的授权配置,确保匿名访问规则生效:
endpoints.MapHealthChecks("/health", new HealthCheckOptions { ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, }).RequireAuthorization(new AuthorizeAttribute { AllowAnonymous = true });
内容的提问来源于stack exchange,提问作者Glen Eccles
相关产品推荐
相关产品推荐

