Blazor HttpClient 如何附加 JWT Token 实现身份验证

来源:前端技术作者:松本一香头衔:网络博主
导读:本期聚焦于小伙伴创作的《Blazor HttpClient 如何附加 JWT Token 实现身份验证》,敬请观看详情。在 Blazor 应用中调用受保护接口时,服务端往往要求请求头携带 JWT 令牌。若直接在页面里手动往 HttpClient 加 Token,不仅散落各处还容易遗漏刷新逻辑。更合理的做法是借助委托处理程序统一拦截请求,在发送前自动写入 Authorization 头。本文说明如何在 Program 中注册具备令牌读取能力的消息处理器,并从认证状态里取出当前用户凭证。相比每处写死请求头,这种方案让令牌管理集中化,也方便处理过期与静默刷新。理解这一机制能帮你少写重复代码,同时避免浏览器端明文暴露密钥的风险。

在 Blazor 应用中,前端经常需要访问带有身份校验的 Web API。服务端通常采用 JWT(JSON Web Token)来识别用户,这就要求每次 HTTP 请求都在头部带上 Authorization 字段。Blazor 的 HttpClient 默认不会自动附加令牌,开发者必须显式处理,否则接口会返回 401。

Blazor HttpClient 如何附加 JWT Token 实现身份验证

为什么不能直接在组件里写 Token

很多初学者会在页面代码的 OnInitialized 或按钮事件里,用 HttpClient.DefaultRequestHeaders.Add 手动塞入 Token。这种做法在小型 demo 里看似可行,但实际项目会带来明显问题。首先,Token 往往存放在本地存储或认证状态里,每个需要调用的组件都要重复读取和赋值,代码冗余且难以维护。

其次,JWT 具有有效期,过期后需要刷新。如果 Token 散落在几十个组件内,刷新逻辑也得写几十遍,极易出现某些请求用了旧令牌而报错的情况。最后,手动添加容易因为大小写、格式错误导致服务端解析失败。因此更推荐通过统一的消息处理管道来自动附加。

使用 DelegatingHandler 统一附加 Token

Blazor 的 HttpClient 基于 .NET 的 HttpMessageHandler 管道,我们可以自定义一个继承自 DelegatingHandler 的类,在 SendAsync 方法中拦截请求并添加头部。这样所有经过该 HttpClient 的请求都会自动带上 JWT,组件层完全无感知。

下面代码展示了一个简单的令牌处理程序,它从注入的 AuthenticationStateProvider 获取当前用户,并读取 Claim 中的 token 声明。如果取到值,就写入 Authorization 头,格式为 Bearer 加空格加令牌内容。

using System.Net.Http.Headers;
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;

public class JwtTokenHandler : DelegatingHandler
{
    private readonly AuthenticationStateProvider _authProvider;

    public JwtTokenHandler(AuthenticationStateProvider authProvider)
    {
        _authProvider = authProvider;
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        // 获取当前认证状态
        var authState = await _authProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        // 从 Claim 中读取 token,注意 Claim 类型需与服务端一致
        var tokenClaim = user.FindFirst("access_token");
        if (tokenClaim != null && !string.IsNullOrEmpty(tokenClaim.Value))
        {
            request.Headers.Authorization =
                new AuthenticationHeaderValue("Bearer", tokenClaim.Value);
        }

        // 调用下一个处理程序或实际发送请求
        return await base.SendAsync(request, cancellationToken);
    }
}

在 Program 中注册处理程序

定义好处理器后,需要在应用入口将其挂到 HttpClient 上。Blazor WebAssembly 或 Server 都可以在 Program.cs 里用 AddHttpMessageHandler 扩展方法完成绑定。同时要注意 HttpClient 的 BaseAddress 必须设置,否则请求会抛异常。

以下示例演示如何注册一个具名 HttpClient,并把 JwtTokenHandler 插入消息管道。通过作用域方式注入 AuthenticationStateProvider,可以保证处理器能拿到最新的登录状态。

using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Http;

var builder = WebAssemblyHostBuilder.CreateDefault(args);

// 注册认证服务(假设已配置好)
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();

// 注册自定义 Token 处理程序
builder.Services.AddScoped<JwtTokenHandler>();

// 配置带 Token 的 HttpClient
builder.Services.AddHttpClient("ApiClient", client =>
{
    client.BaseAddress = new Uri("https://ipipp.com/api/");
}).AddHttpMessageHandler<JwtTokenHandler>();

// 也可以提供一个方便注入的强类型客户端
builder.Services.AddScoped(sp =>
    sp.GetRequiredService<IHttpClientFactory>()
      .CreateClient("ApiClient"));

await builder.Build().RunAsync();

在组件中调用带 Token 的客户端

注册完成后,组件只需通过 IHttpClientFactory 或直接注入命名客户端来发起请求,不再关心 Token 细节。下面例子展示在 Razor 组件里获取天气数据,由于管道已自动附加 JWT,代码非常干净。

如果服务端返回 401,说明 Token 失效或 Claim 名称不匹配,此时应引导用户重新登录,而不是在业务代码里反复判断头部。集中式的处理器让异常拦截和全局刷新令牌都更容易实现。

@inject IHttpClientFactory HttpClientFactory
@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        var client = HttpClientFactory.CreateClient("ApiClient");
        // 不需要手动加 Token,处理程序已自动附加
        forecasts = await client.GetFromJsonAsync<WeatherForecast[]>("weather");
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
    }
}

常见误区与注意事项

一个容易被忽略的点是:在 Blazor Server 端注入的 HttpClient 如果是单例,而 AuthenticationStateProvider 是作用域,会导致处理器取不到用户。因此 JwtTokenHandler 必须注册为 Scoped 或 Transient,而不能是 Singleton。否则会出现明明已登录,请求却不带 Token 的诡异现象。

另一个误区是在浏览器端把 JWT 存到本地存储后,认为加个处理程序就安全了。实际上 Token 仍可能被 XSS 脚本读取,关键接口应配合 CSP 策略和短时有效期。此外,若 API 和 Blazor 应用跨域,服务端需正确配置 CORS 允许 Authorization 头,否则预检请求会失败。

方案优点缺点
组件内手动加 Token简单直观,无需额外类重复代码,难维护,刷新易漏
DelegatingHandler 统一加集中管理,组件干净,易扩展需理解管道与生命周期注册
HttpMessageHandler 全局静态性能略高无法感知用户状态,不适用多用户

总结

通过 DelegatingHandler 为 Blazor 的 HttpClient 附加 JWT Token,是兼顾可维护性与安全性的标准做法。它将令牌读取、格式组装、过期处理都收敛到一处,业务组件只管调用接口。只要注意处理程序的生命周期注册和 Claim 名称对齐,就能稳定支撑受保护 API 的访问需求。

BlazorHttpClientJWT_Token修改时间:2026-08-06 07:21:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。