You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 Blazor Server中JWT令牌注入HTTP请求管道问题求助

.NET 8 Blazor Server中JWT令牌集成到HTTP请求管道的解决方案

问题根源分析

  • Refit配置中使用GetAwaiter().GetResult()同步阻塞异步操作,在Blazor Server的单线程同步上下文下会导致死锁,无法正确获取令牌。
  • 委托处理器依赖缓存的_tokenProvider,没有实时从ProtectedSessionStorage读取最新令牌,可能使用过期或空值。

修正方案

1. 修复Refit的令牌获取逻辑

将同步等待改为异步实现,利用AuthorizationHeaderValueGetter的异步支持:

public RefitService(IHttpClientFactory http, ProtectedSessionStorage sessionStorage)
{
    _client = http.CreateClient(HTTP_CLIENT_KEY);
    _sessionStorage = sessionStorage;

    _refitSettings = new(new NewtonsoftJsonContentSerializer())
    {
        AuthorizationHeaderValueGetter = async (request, cancellationToken) =>
        {
            TokenProvider tokenProvider = await GetTokenProvide(cancellationToken);
            return tokenProvider.AccessToken;
        }
    };
}

// 实现支持取消令牌的异步获取方法
private async Task<TokenProvider> GetTokenProvide(CancellationToken cancellationToken)
{
    var result = await _sessionStorage.GetAsync<TokenProvider>("tokenKey", cancellationToken);
    return result.Success ? result.Value : new TokenProvider();
}

2. 修正委托处理器的实时令牌获取

每次请求时直接从ProtectedSessionStorage读取令牌,避免依赖缓存:

public class JwtAuthorizationHandler : DelegatingHandler
{
    private readonly ProtectedSessionStorage _sessionStorage;

    public JwtAuthorizationHandler(ProtectedSessionStorage sessionStorage)
    {
        _sessionStorage = sessionStorage;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var tokenResult = await _sessionStorage.GetAsync<TokenProvider>("tokenKey", cancellationToken);
        if (tokenResult.Success && !string.IsNullOrWhiteSpace(tokenResult.Value.AccessToken))
        {
            // 注意Bearer后面不要加多余空格
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResult.Value.AccessToken);
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

3. 正确注册委托处理器

在Program.cs中注册处理器并关联到HttpClient:

builder.Services.AddScoped<JwtAuthorizationHandler>();

builder.Services.AddHttpClient(HTTP_CLIENT_KEY)
    .AddHttpMessageHandler<JwtAuthorizationHandler>();

4. 验证PersistentAuthenticationStateProvider的令牌读取

确保GetTokenProvide方法正确从存储读取令牌:

private async Task<TokenProvider> GetTokenProvide()
{
    var result = await ProtectedSessionStorage.GetAsync<TokenProvider>("tokenKey");
    return result.Success ? result.Value : new TokenProvider();
}

关键注意事项

  • 绝对避免在Blazor Server中使用GetAwaiter().GetResult()、Result等同步阻塞异步操作的写法,会触发死锁。
  • 确保令牌存储的键名(如示例中的tokenKey)在存入、读取时完全一致。
  • 检查Bearer头的格式,不要在Bearer和令牌之间添加多余空格。

内容的提问来源于stack exchange,提问作者kyenry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:22:52