为何注入的HttpClient.DefaultRequestHeaders.Authorization值为null?
问题核心原因
你猜测的两次注入获得不同HttpClient实例是首要诱因:
- 默认调用
services.AddHttpClient()时,注入的HttpClient属于瞬态(Transient)生命周期,每次不同的类构造请求注入时,都会创建全新的HttpClient实例。你在MyAuthenticationService里给注入的实例设置的请求头,完全不会同步到其他服务注入的不同HttpClient实例上,自然读取Authorization头的时候就是null,发起API请求就会返回401错误。
可行解决方案
方案1:使用命名HttpClient保证实例配置统一
通过IHttpClientFactory创建固定名称的HttpClient,所有服务统一用该名称获取客户端,保证配置同步:
- 注册时配置命名客户端:
services.AddHttpClient("GlobalApiClient", client => { // 可预先配置API基础地址等通用配置 client.BaseAddress = new Uri("你的API根地址"); });
- 认证服务中注入
IHttpClientFactory设置请求头:
public MyAuthenticationService(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } private void AddAccessTokenToHttpClientHeader(string accessToken) { var client = _httpClientFactory.CreateClient("GlobalApiClient"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken); }
- 业务服务中用同一名称获取客户端发起请求:
public YourBusinessService(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } public async Task<T> CallApi() { var client = _httpClientFactory.CreateClient("GlobalApiClient"); // 此时Authorization头已正确存在 return await ApiUtils.GetList<T>(client, uri, _logger); }
方案2:使用委托处理器自动附加授权头(更推荐)
该方案无需手动维护HttpClient的头配置,每次发起请求时自动附加token,避免实例不同步问题:
- 自定义授权请求处理器:
public class AuthHeaderHandler : DelegatingHandler { private readonly AuthenticationStateProvider _authStateProvider; public AuthHeaderHandler(AuthenticationStateProvider authStateProvider) { _authStateProvider = authStateProvider; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var authState = await _authStateProvider.GetAuthenticationStateAsync(); if (authState.User.Identity?.IsAuthenticated == true) { // 从认证声明或持久化存储中读取token var token = authState.User.FindFirst("access_token")?.Value; if (!string.IsNullOrEmpty(token)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } } return await base.SendAsync(request, cancellationToken); } }
- 注册处理器并绑定到HttpClient:
services.AddScoped<AuthHeaderHandler>(); services.AddHttpClient("GlobalApiClient", client => { client.BaseAddress = new Uri("你的API根地址"); }).AddHttpMessageHandler<AuthHeaderHandler>();
其他可能的排查方向
如果已经使用同一命名HttpClient仍出现该问题,可排查以下两点:
- 若你使用的是Blazor WebAssembly项目,页面刷新后内存中存储的token会丢失,需要将token持久化到
localStorage或sessionStorage,应用初始化时重新读取赋值。 - 检查两个服务的生命周期:如果
MyAuthenticationService注册为单例,而业务服务注册为作用域/瞬态,也会出现实例配置不同步的问题。
内容的提问来源于stack exchange,提问作者Napoleon
相关产品推荐
相关产品推荐

