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

Blazor Server应用中如何将登录页排除在基于Token的授权之外?

问题分析与解决方案

你遇到的控制台报错,核心原因是当token为空时,ParseClaimsFromJwt方法直接对空字符串执行Split('.')操作,导致索引越界异常——这和[AllowAnonymous]无关,因为AllowAnonymous只是跳过路由授权校验,但Blazor的AuthenticationStateProvider会在所有页面加载时被调用,用于获取当前用户的认证状态,所以空token的场景必须在AuthStateProvider内部处理。

第一步:修复CustomAuthStateProvider核心逻辑

修改GetAuthenticationStateAsync方法,先判断token是否有效;同时给ParseClaimsFromJwt增加参数校验,避免非法token导致崩溃。

修改后的完整代码:

public class CustomAuthStateProvider : AuthenticationStateProvider
{
    private readonly ILocalStorageService _localStorageService;

    public CustomAuthStateProvider(ILocalStorageService localStorageService)
    {
        _localStorageService = localStorageService;
    }

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        string token = await _localStorageService.GetItem<string>("token");

        ClaimsIdentity identity;
        if (!string.IsNullOrEmpty(token) && IsValidJwtFormat(token))
        {
            // 解析有效token,创建认证身份
            identity = new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt");
        }
        else
        {
            // token为空或格式无效,创建匿名身份
            identity = new ClaimsIdentity();
        }

        var user = new ClaimsPrincipal(identity);
        var state = new AuthenticationState(user);

        NotifyAuthenticationStateChanged(Task.FromResult(state));

        return state;
    }

    // 简单校验JWT格式是否符合三段式结构
    private bool IsValidJwtFormat(string jwt)
    {
        return jwt?.Split('.').Length == 3;
    }

    public static IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
    {
        // 增加参数校验,避免空值或格式错误的token引发异常
        if (string.IsNullOrEmpty(jwt) || jwt.Split('.').Length != 3)
        {
            return Enumerable.Empty<Claim>();
        }

        var payload = jwt.Split('.')[1];
        var jsonBytes = ParseBase64WithoutPadding(payload);
        var keyValuePairs = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);

        return keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString()));
    }

    private static byte[] ParseBase64WithoutPadding(string base64)
    {
        switch (base64.Length % 4)
        {
            case 2: base64 += "=="; break;
            case 3: base64 += "="; break;
        }
        return Convert.FromBase64String(base64);
    }
}

第二步:确保登录页的[AllowAnonymous]正确配置

虽然这不是当前报错的原因,但需确保登录页(如Login.razor)顶部正确标记,避免路由层面的拦截:

@page "/login"
@attribute [AllowAnonymous]

关键修复点说明

  1. 空token处理:当token为空或格式无效时,创建空的ClaimsIdentity(不指定认证类型),此时ClaimsPrincipal会被识别为匿名用户,符合未登录状态。
  2. 格式校验:新增IsValidJwtFormat方法快速判断token是否符合JWT三段式结构,避免无效token进入解析流程。
  3. 参数防护:在ParseClaimsFromJwt中增加参数校验,即使外部传入非法token,也不会抛出异常,而是返回空的Claim集合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:35:00