You need to enable JavaScript to run this app. 为何注入的HttpClient.DefaultRequestHeaders.Authorization值为null?
优惠活动
大模型
产品
解决方案
定价
更多

为何注入的HttpClient.DefaultRequestHeaders.Authorization值为null?

问题核心原因

你猜测的两次注入获得不同HttpClient实例是首要诱因:

  • 默认调用services.AddHttpClient()时,注入的HttpClient属于瞬态(Transient)生命周期,每次不同的类构造请求注入时,都会创建全新的HttpClient实例。你在MyAuthenticationService里给注入的实例设置的请求头,完全不会同步到其他服务注入的不同HttpClient实例上,自然读取Authorization头的时候就是null,发起API请求就会返回401错误。

可行解决方案

方案1:使用命名HttpClient保证实例配置统一

通过IHttpClientFactory创建固定名称的HttpClient,所有服务统一用该名称获取客户端,保证配置同步:

  1. 注册时配置命名客户端:
services.AddHttpClient("GlobalApiClient", client =>
{
    // 可预先配置API基础地址等通用配置
    client.BaseAddress = new Uri("你的API根地址");
});
  1. 认证服务中注入IHttpClientFactory设置请求头:
public MyAuthenticationService(IHttpClientFactory httpClientFactory)
{
    _httpClientFactory = httpClientFactory;
}

private void AddAccessTokenToHttpClientHeader(string accessToken)
{
    var client = _httpClientFactory.CreateClient("GlobalApiClient");
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
}
  1. 业务服务中用同一名称获取客户端发起请求:
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,避免实例不同步问题:

  1. 自定义授权请求处理器:
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);
    }
}
  1. 注册处理器并绑定到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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 08:33:02