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

基于分布式缓存实现Blazor Server用户SSO状态持久化问题排查

问题分析与解决方案

针对你在Blazor Server + Azure B2C场景下遇到的应用重启后用户状态丢失问题,核心原因是默认配置下认证会话和令牌缓存都存在内存中,重启后即被清除。结合你的配置,当前存在几个关键遗漏和错误,以下是具体修复方案:

一、关键问题排查

  1. 缓存组件与数据库不匹配:你启动了MySQL服务器,但使用的是Microsoft.Extensions.Caching.SqlServer包(仅适配SQL Server),两者无法兼容,导致缓存数据无法写入。
  2. 未配置认证会话持久化:Blazor Server默认将认证会话存储在内存中,需手动替换为分布式存储才能跨重启保留状态。
  3. 缺少DataProtection密钥持久化:认证会话数据是加密存储的,若密钥仅存于内存,重启后密钥丢失,即使会话数据存在也无法解密。

二、分步修复方案

1. 匹配缓存组件与数据库

根据你使用的数据库选择对应分布式缓存包:

  • 若用SQL Server:保持Microsoft.Extensions.Caching.SqlServer包,确保连接字符串指向SQL Server实例。
  • 若用MySQL:卸载SqlServer缓存包,安装适配MySQL的缓存组件,例如Microsoft.Extensions.Caching.MySql或第三方实现(如StackExchange.Redis更通用,但需额外部署Redis服务)。

2. 配置DataProtection密钥持久化

认证会话的加密密钥需持久化到数据库,避免重启后失效:

// Program.cs
builder.Services.AddDataProtection()
    .PersistKeysToSqlServer(new SqlConnection(builder.Configuration.GetConnectionString("YourDbConnection")),
        new TableConfiguration("DataProtectionKeys", "dbo"));

需提前创建DataProtectionKeys表,可通过EF迁移或手动执行官方提供的SQL脚本生成。

3. 配置分布式认证会话存储

将Blazor Server默认的内存认证会话替换为分布式缓存:

// 先配置分布式缓存(以SQL Server为例)
builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString("YourDbConnection");
    options.SchemaName = "dbo";
    options.TableName = "Session";
});

// 配置Azure B2C认证,并指定会话存储为分布式缓存
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(options =>
    {
        builder.Configuration.Bind("AzureAdB2C", options);
        // 开启持久化登录配置
        options.UseTokenLifetime = false; // 不依赖令牌生命周期,使用自定义会话周期
        options.SlidingExpiration = true; // 滑动过期,延长会话有效期
        options.RemoteAuthenticationOptions.Cookie.MaxAge = TimeSpan.FromDays(7); // 设置会话有效期
    })
    .EnableTokenAcquisitionToCallDownstreamApi(new List<string> { "<your-scopes>" })
    .AddDistributedTokenCaches(); // 持久化下游API令牌缓存

// 关键:将认证会话绑定到分布式缓存
builder.Services.Configure<AuthenticationOptions>(options =>
{
    var serviceProvider = builder.Services.BuildServiceProvider();
    options.SessionStore = new DistributedSessionStore(
        serviceProvider.GetRequiredService<IDistributedCache>(),
        serviceProvider.GetRequiredService<ILoggerFactory>());
});

4. 修正中间件顺序

确保中间件执行顺序正确,在Program.cs中按以下顺序添加:

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

// 若使用Session,需放在UseAuthentication之前
// app.UseSession();

app.UseAuthentication();
app.UseAuthorization();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

三、验证步骤

  1. 确认数据库连接字符串正确,且Session、DataProtectionKeys表结构无误。
  2. 启动应用并完成登录,检查数据库中Session表是否有数据写入。
  3. 重启应用,刷新页面,验证用户是否保持登录状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:22:13