基于分布式缓存实现Blazor Server用户SSO状态持久化问题排查
问题分析与解决方案
针对你在Blazor Server + Azure B2C场景下遇到的应用重启后用户状态丢失问题,核心原因是默认配置下认证会话和令牌缓存都存在内存中,重启后即被清除。结合你的配置,当前存在几个关键遗漏和错误,以下是具体修复方案:
一、关键问题排查
- 缓存组件与数据库不匹配:你启动了MySQL服务器,但使用的是
Microsoft.Extensions.Caching.SqlServer包(仅适配SQL Server),两者无法兼容,导致缓存数据无法写入。 - 未配置认证会话持久化:Blazor Server默认将认证会话存储在内存中,需手动替换为分布式存储才能跨重启保留状态。
- 缺少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");
三、验证步骤
- 确认数据库连接字符串正确,且
Session、DataProtectionKeys表结构无误。 - 启动应用并完成登录,检查数据库中
Session表是否有数据写入。 - 重启应用,刷新页面,验证用户是否保持登录状态。
内容的提问来源于stack exchange,提问作者Christopher Dunderdale
相关产品推荐
相关产品推荐

