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

如何为Blazor WebAssembly(PWA)与IdentityServer 4配置持久化登录

解决Blazor WASM PWA + IdentityServer4登录状态持久化问题

看起来你遇到的核心问题是认证会话无法跨浏览器会话持久,且活跃状态下1小时就过期,这其实涉及到IdentityServer的会话Cookie配置、Blazor客户端的认证状态存储,以及关键的Refresh Token自动续期机制。结合你给出的配置,我来一步步帮你解决:

一、先搞懂核心逻辑

你提到的access token生命周期(1小时)确实和用户重新认证无关——access token过期后,应该用refresh token自动获取新的access token,而不是让用户重新登录。另外,Blazor WASM默认用sessionStorage存储认证状态,关闭标签页就会丢失,这也是跨会话丢失登录状态的原因。

二、修改IdentityServer客户端配置,启用Refresh Token

你的客户端配置里缺少Refresh Token相关设置,这是自动续期的关键。更新Client代码如下:

new Client { 
  ClientId = "MyBlazorClient", 
  ClientName = "My Blazor Client Application", 
  RequireClientSecret = false, 
  AllowedCorsOrigins = { "https://localhost:443" }, 
  AllowedGrantTypes = GrantTypes.Code, 
  RedirectUris = { "https://localhost:443/authentication/login-callback" }, 
  PostLogoutRedirectUris = { "https://localhost:443/authentication/logout-callback" }, 
  AllowedScopes = new List<string> { 
    IdentityServerConstants.StandardScopes.OpenId, 
    IdentityServerConstants.StandardScopes.Profile, 
    IdentityServerConstants.StandardScopes.OfflineAccess, // 新增:获取refresh token必须的scope
    "roles", "claims" 
  }, 
  RequirePkce = true, 
  AllowPlainTextPkce = false,
  AllowOfflineAccess = true, // 新增:允许客户端请求离线访问(即refresh token)
  RefreshTokenExpiration = TokenExpiration.Sliding, // 滑动过期:用户活跃就自动续期
  SlidingRefreshTokenLifetime = 28800, // 4小时滑动窗口(用户每活跃一次就延长4小时)
  AbsoluteRefreshTokenLifetime = 86400, // 最长24小时:即使一直活跃,超过这个时间也需重新登录
  RefreshTokenUsage = TokenUsage.ReUse // 允许重复使用refresh token(更方便,若追求安全可选OneTimeOnly)
}

三、调整Blazor WASM客户端配置,持久化认证状态

你的客户端当前没有配置持久化存储和自动刷新,修改Program.cs的OIDC配置:

builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("IdentityService", options.ProviderOptions);
    
    // 把认证状态从sessionStorage改为localStorage,实现跨会话持久
    options.AuthenticationStateProviderOptions.AuthenticationSessionStorage = new LocalStorageAuthenticationSessionStorage();
    
    // 确保请求offline_access scope,获取refresh token
    options.ProviderOptions.Scope.Add("offline_access");
    // 保存tokens到存储,框架会自动用refresh token刷新过期的access token
    options.ProviderOptions.SaveTokens = true;
});

同时更新appsettings.json的默认Scope:

"IdentityService": { 
  "Authority": "https://localhost:44362", 
  "ClientId": "MyBlazorClient", 
  "DefaultScopes": [ "openid", "profile", "claims", "roles", "offline_access" ], // 新增offline_access
  "ResponseType": "code" 
}

四、完善IdentityServer的Cookie配置

你已经设置了CookieLifetime和CookieSlidingExpiration,但还要确保Cookie是持久化的(关闭浏览器后不丢失),更新IdentityServer的Authentication配置:

options.Authentication = new AuthenticationOptions() { 
  CookieLifetime = TimeSpan.FromHours(8), 
  CookieSlidingExpiration = true,
  CookieIsPersistent = true, // 新增:让Cookie持久化存储到浏览器
  CookieSameSite = SameSiteMode.Lax // 适配移动设备的Cookie策略
};

五、PWA移动设备额外优化

因为你的应用是PWA,在移动后台运行时,可以监听应用前台切换事件,主动检查token有效性:

@inject IAuthenticationStateProvider AuthenticationStateProvider
@inject IAccessTokenProvider TokenProvider

@code {
    protected override async Task OnInitializedAsync()
    {
        // 监听应用从后台回到前台的事件
        document.addEventListener("visibilitychange", async () =>
        {
            if (!document.hidden)
            {
                // 检查当前token是否过期,若过期触发自动刷新
                var tokenResult = await TokenProvider.RequestAccessToken();
                if (tokenResult.TryGetToken(out var token) && token.Expires < DateTimeOffset.UtcNow)
                {
                    await ((OidcAuthenticationStateProvider)AuthenticationStateProvider).GetAuthenticationStateAsync();
                }
            }
        });
    }
}

常见排查点

  • 浏览器第三方Cookie:如果用户浏览器禁用了第三方Cookie,IdentityServer的会话Cookie会丢失,需要引导用户开启,或设置CookieSameSite = SameSiteMode.None(需HTTPS)
  • 隐私模式:部分浏览器隐私模式会禁用localStorage,这种情况只能用sessionStorage,持久化会受限
  • Refresh Token生命周期:如果AbsoluteRefreshTokenLifetime设置过短,即使用户活跃,到期后仍需重新登录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 09:48:16