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

如何在ASP.NET Core 8.0 Blazor中结合外部API与JWT Token实现认证流程?

创建InteractiveAuto模式的Blazor应用对接自定义JWT API

1. 创建基础项目

用.NET CLI创建Interactive Auto模式的Blazor Web App:

dotnet new blazor -n MyJwtBlazorApp -int Auto

或在Visual Studio中选择「Blazor Web App」模板,交互模式选「Interactive Auto」,取消勾选「Enable Identity」(若默认勾选)。

2. 清理默认Identity内容

若创建时未取消Identity,手动清理:

  • 删除Pages/Account文件夹
  • 在Program.cs中移除Identity相关服务配置,比如AddDbContext<ApplicationDbContext>、AddDefaultIdentity、AddEntityFrameworkStores等代码块

3. 配置JWT认证服务

在Program.cs中添加适配自定义API的JWT认证配置:

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = "你的API发行者",
        ValidAudience = "你的API受众",
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("你的API密钥"))
    };

    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
            if (!string.IsNullOrEmpty(token))
            {
                context.Token = token;
            }
            return Task.CompletedTask;
        }
    };
});

builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<AuthenticationStateProvider, JwtAuthenticationStateProvider>();

4. 自定义AuthenticationStateProvider

创建JwtAuthenticationStateProvider.cs,处理客户端与服务器端的认证状态同步:

public class JwtAuthenticationStateProvider : AuthenticationStateProvider
{
    private readonly HttpClient _httpClient;
    private readonly IJSRuntime _jsRuntime;

    public JwtAuthenticationStateProvider(HttpClient httpClient, IJSRuntime jsRuntime)
    {
        _httpClient = httpClient;
        _jsRuntime = jsRuntime;
    }

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var token = string.Empty;

#if WASM
        token = await _jsRuntime.InvokeAsync<string>("localStorage.getItem", "authToken");
#else
        var authHeader = _httpClient.DefaultRequestHeaders.Authorization;
        token = authHeader?.Parameter;
#endif

        if (string.IsNullOrEmpty(token))
        {
            return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
        }

        var handler = new JwtSecurityTokenHandler();
        var jwtToken = handler.ReadJwtToken(token);
        var claims = jwtToken.Claims.ToList();
        var identity = new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme);
        var user = new ClaimsPrincipal(identity);

        return new AuthenticationState(user);
    }

    public void UpdateAuthenticationState(string token)
    {
#if WASM
        _jsRuntime.InvokeVoidAsync("localStorage.setItem", "authToken", token);
#endif
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }
}

5. 实现登录组件

创建Pages/Login.razor,对接API获取JWT并更新认证状态:

@page "/login"
@inject HttpClient Http
@inject AuthenticationStateProvider AuthStateProvider
@inject NavigationManager NavManager

<h3>登录</h3>

<div class="login-form">
    <label>用户名:</label>
    <input @bind="Username" class="form-input" />
</div>
<div class="login-form">
    <label>密码:</label>
    <input type="password" @bind="Password" class="form-input" />
</div>
<button @onclick="Login" class="login-btn">登录</button>

@code {
    private string Username { get; set; }
    private string Password { get; set; }

    private async Task Login()
    {
        var loginModel = new { Username, Password };
        var response = await Http.PostAsJsonAsync("你的API登录接口地址", loginModel);
        
        if (response.IsSuccessStatusCode)
        {
            var token = await response.Content.ReadAsStringAsync();
            ((JwtAuthenticationStateProvider)AuthStateProvider).UpdateAuthenticationState(token);
            NavManager.NavigateTo("/");
        }
        else
        {
            // 处理登录失败逻辑,比如提示错误
        }
    }
}

6. 配置路由与授权

修改App.razor,确保认证状态正确传递并处理授权逻辑:

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    @if (!context.User.Identity.IsAuthenticated)
                    {
                        <RedirectToLogin />
                    }
                    else
                    {
                        <p>你没有权限访问此页面。</p>
                    }
                </NotAuthorized>
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>页面不存在</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>抱歉,找不到你要访问的页面。</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

7. 客户端请求自动携带Token

创建JwtAuthorizationHandler.cs,让客户端HttpClient自动添加Authorization头:

public class JwtAuthorizationHandler : DelegatingHandler
{
    private readonly IJSRuntime _jsRuntime;

    public JwtAuthorizationHandler(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var token = await _jsRuntime.InvokeAsync<string>("localStorage.getItem", "authToken");
        if (!string.IsNullOrEmpty(token))
        {
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
        }
        return await base.SendAsync(request, cancellationToken);
    }
}

在客户端项目(.Client文件夹下的Program.cs)中注册:

builder.Services.AddScoped<JwtAuthorizationHandler>();
builder.Services.AddHttpClient("ApiClient", client => 
    client.BaseAddress = new Uri("你的API基础地址"))
    .AddHttpMessageHandler<JwtAuthorizationHandler>();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 04:35:26