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

Blazor Server设置forceLoad:true导航时触发IAuthenticationService错误

Blazor Server 强制加载/刷新页面时身份验证崩溃问题

问题背景

开发一款展示数据库数据的内部工具,通过自定义CustomAuthStateProvider管理身份验证,支持登录、注销功能,权限限制逻辑运行正常。

触发场景与错误

使用以下导航代码时,仅当设置forceLoad: true会导致应用崩溃:

NavigationManager.NavigateTo($"/myPage/dateFrom={System.Uri.EscapeUriString(fromStr)}/dateTo={System.Uri.EscapeUriString(toStr)}", forceLoad: true);

错误提示:

InvalidOperationException: 找不到所需的'IAuthenticationService'服务。请在应用启动代码中调用'IServiceCollection.AddAuthentication'添加所有必需的服务。

额外发现:手动在浏览器地址栏输入应用URL并回车刷新时,会出现相同错误。

后续尝试与新错误

重构部分身份验证逻辑后,出现新错误:

可通过AddAuthentication(string defaultScheme)或AddAuthentication(Action configureOptions)设置默认方案。

尝试过相关解决方案但未解决问题。


相关代码

CustomAuthStateProvider.cs

using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
using System.Threading.Tasks;

public class CustomAuthStateProvider : AuthenticationStateProvider
{
    public CustomAuthStateProvider()
    {
        this.CurrentUser = this.GetAnonymous();
    }

    private ClaimsPrincipal CurrentUser { get; set; }

    private ClaimsPrincipal GetUser(string userName, uint id, string role)
    {
        var identity = new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes.Sid, id.ToString(new System.Globalization.CultureInfo("de-DE"))),
            new Claim(ClaimTypes.Name, userName),
            new Claim(ClaimTypes.Role, role)
        },  "Authentication type");
        return new ClaimsPrincipal(identity);
    }

    private ClaimsPrincipal GetAnonymous()
    {
        var identity = new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes.Sid, "0"),
            new Claim(ClaimTypes.Name, "Anonymous"),
            new Claim(ClaimTypes.Role, "Anonymous")
        }, null);
        return new ClaimsPrincipal(identity);
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var task = Task.FromResult(new AuthenticationState(this.CurrentUser));
        return task;
    }

    public Task<AuthenticationState> ChangeUser(string username, uint id, string role)
    {
        this.CurrentUser = this.GetUser(username, id, role);
        var task = this.GetAuthenticationStateAsync();
        this.NotifyAuthenticationStateChanged(task);
        return task;
    }

    public Task<AuthenticationState> Logout()
    {
        this.CurrentUser = this.GetAnonymous();
        var task = this.GetAuthenticationStateAsync();
        this.NotifyAuthenticationStateChanged(task);
        return task;
    }
}

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add MudBlazor services
builder.Services.AddMudServices();

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

builder.Services.AddSingleton<InitializationStateService>(); // Logging

builder.Services.AddScoped<CustomAuthStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<CustomAuthStateProvider>());
builder.Services.AddAuthorizationCore();

builder.Services.AddServerSideBlazor().AddCircuitOptions(options =>
{
    options.DetailedErrors = true;
    options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromSeconds(0);
    options.DisconnectedCircuitMaxRetained = 0;
});

builder.Services.AddHealthChecks();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
}

app.UseStaticFiles();
app.UseAntiforgery();

app.UseHealthChecks("/health");

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

解决方案

问题根源:当使用forceLoad: true或手动刷新页面时,会触发服务器端初始渲染,此时Blazor会尝试调用ASP.NET Core的身份验证中间件,但当前仅注册了AddAuthorizationCore(仅提供授权逻辑,无身份验证服务),缺少IAuthenticationService的实现。

修复步骤

  1. 添加身份验证服务并设置默认方案
    修改Program.cs中的服务注册代码,将builder.Services.AddAuthorizationCore();替换为:

    // 添加身份验证服务并设置默认方案
    builder.Services.AddAuthentication(options =>
    {
        options.DefaultScheme = "CustomScheme";
    })
    // 添加空的自定义身份验证处理程序
    .AddScheme<AuthenticationSchemeOptions, CustomAuthenticationHandler>("CustomScheme", options => { });
    
    // 保留授权服务注册
    builder.Services.AddAuthorizationCore();
    
  2. 创建自定义身份验证处理程序
    新增CustomAuthenticationHandler.cs文件:

    using Microsoft.AspNetCore.Authentication;
    using System.Security.Claims;
    using System.Threading.Tasks;
    
    public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
    {
        public CustomAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
            : base(options, logger, encoder, clock)
        {
        }
    
        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            // 由于使用CustomAuthStateProvider管理用户状态,此处返回失败即可
            return Task.FromResult(AuthenticateResult.Fail("无身份验证操作"));
        }
    }
    
  3. 调整中间件顺序
    在Program.cs的请求管道中添加UseAuthentication中间件:

    app.UseStaticFiles();
    app.UseAuthentication(); // 添加此中间件
    app.UseAntiforgery();
    

原理说明

  • AddAuthentication会注册IAuthenticationService,解决找不到服务的错误;
  • 空的自定义处理程序用于满足ASP.NET Core身份验证框架的要求,实际用户状态仍由CustomAuthStateProvider管理;
  • 中间件顺序确保身份验证服务在请求管道中提前初始化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:25:16