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

Blazor WebAssembly迁移身份验证授权模板代码失败

Blazor WebAssembly 身份验证迁移故障排查

我将Visual Studio最新更新的Identity模板中的身份验证与授权代码迁移到自己的Blazor WebAssembly(客户端-服务器)Web应用后出现错误,以下是已执行的操作及问题:

AccountController.cs(已调试,无问题)

[HttpPost]
[Route("/api/account/login")]
public async Task<SignInResult> Login([FromBody] LoginModel model)
{
    var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, false);

    return result;
}

PersistingServerAuthenticationStateProvider.cs(登录时完全未进入此类,是否正常?)

internal sealed class PersistingServerAuthenticationStateProvider : ServerAuthenticationStateProvider, IDisposable
{
    private readonly PersistentComponentState state;
    private readonly IdentityOptions options;

    private readonly PersistingComponentStateSubscription subscription;

    private Task<AuthenticationState>? authenticationStateTask;

    public PersistingServerAuthenticationStateProvider(
        PersistentComponentState persistentComponentState,
        IOptions<IdentityOptions> optionsAccessor)
    {
        state = persistentComponentState;
        options = optionsAccessor.Value;

        AuthenticationStateChanged += OnAuthenticationStateChanged;
        subscription = state.RegisterOnPersisting(OnPersistingAsync, RenderMode.InteractiveWebAssembly);
    }

    private void OnAuthenticationStateChanged(Task<AuthenticationState> task)
    {
        authenticationStateTask = task;
    }

    private async Task OnPersistingAsync()
    {
        if (authenticationStateTask is null)
        {
            throw new UnreachableException($"Authentication state not set in {nameof(OnPersistingAsync)}().");
        }

        var authenticationState = await authenticationStateTask;
        var principal = authenticationState.User;

        if (principal.Identity?.IsAuthenticated == true)
        {
            var userId = principal.FindFirst(options.ClaimsIdentity.UserIdClaimType)?.Value;
            var email = principal.FindFirst(options.ClaimsIdentity.EmailClaimType)?.Value;

            if (userId != null && email != null)
            {
                state.PersistAsJson(nameof(UserInfo), new UserInfo
                {
                    UserId = userId,
                    Email = email,
                });
            }
        }
    }

    public void Dispose()
    {
        subscription.Dispose();
        AuthenticationStateChanged -= OnAuthenticationStateChanged;
    }
}

PersistentAuthenticationStateProvider(验证时始终返回空值,访问授权页面未进入此类方法)

构造函数中始终进入return分支,导致认证状态始终为未认证:

public class PersistentAuthenticationStateProvider : AuthenticationStateProvider
{
    private static readonly Task<AuthenticationState> defaultUnauthenticatedTask =
Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));

    private readonly Task<AuthenticationState> authenticationStateTask = defaultUnauthenticatedTask;

    public PersistentAuthenticationStateProvider(PersistentComponentState state)
    {
        if (!state.TryTakeFromJson<UserInfo>(nameof(UserInfo), out var userInfo) || userInfo is null)
        {
            return; // 始终进入此处
        }

        Claim[] claims = [
            new Claim(ClaimTypes.NameIdentifier, userInfo.UserId),
            new Claim(ClaimTypes.Name, userInfo.Email),
            new Claim(ClaimTypes.Email, userInfo.Email) ];

        authenticationStateTask = Task.FromResult(
            new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims,
                authenticationType: nameof(PersistentAuthenticationStateProvider)))));
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync() => authenticationStateTask;
}

注册配置

  • 服务器端Program.cs已注册PersistingServerAuthenticationStateProvider
  • 客户端Program.cs已注册PersistentAuthenticationStateProvider

与模板项目的核心差异:我的项目中Login.razor视图位于客户端,而模板生成的视图位于服务器端。

目前核心问题:PersistingServerAuthenticationStateProvider完全无法触发调试断点,怀疑遗漏了关键配置步骤。

客户端注册代码

builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddSingleton<AuthenticationStateProvider, PersistentAuthenticationStateProvider>();

服务器端注册代码

builder.Services.AddDbContext<IdentityDataContext>((options) =>
{
    options.UseSqlServer(databaseConfig?.ConnectionString);
});
builder.Services.AddIdentityCore<User>()//options => options.SignIn.RequireConfirmedAccount = true
    .AddEntityFrameworkStores<IdentityDataContext>()
    .AddSignInManager()
    .AddDefaultTokenProviders();

builder.Services.AddScoped<UserManager<User>>();
builder.Services.AddScoped<AuthenticationStateProvider, PersistingServerAuthenticationStateProvider>();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:02:33