.NET7中Blazor客户端与Duende SSO登出后无法自动跳转登录页问题
问题:SSO登出后Blazor客户端无法自动跳转登录页
我有一个Blazor客户端和使用Duende Identity Server的SSO服务器,当前项目基于.NET7。访问Blazor应用链接https://localhost:7244时会自动重定向到SSO登录,此功能正常。但在SSO端登出后,Blazor客户端的Cookie已被清除,SSO端显示登出完成,但Blazor客户端不会自动重定向到登录页,必须手动刷新页面(F5)才会生效。需要实现SSO登出后Blazor客户端自动跳转到登录页。
SSO端program.cs配置
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<BeaconSSOContext>(); builder.Services.AddIdentityServer() .AddInMemoryClients(new Client[] { new Client { ClientId = "client", AllowedGrantTypes = GrantTypes.Implicit, RedirectUris = { "https://localhost:7244/signin-oidc" }, PostLogoutRedirectUris = { "https://localhost:7244/signout-callback-oidc" }, FrontChannelLogoutUri = "https://localhost:7244/signout-oidc", AllowedScopes = { "openid", "profile", "email", "phone" } } }) .AddInMemoryIdentityResources(new IdentityResource[] { new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Email(), new IdentityResources.Phone(), }) .AddAspNetIdentity<IdentityUser>();
Blazor客户端program.cs配置
// Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); builder.Services.AddAuthentication(options => { options.DefaultScheme = "cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("cookies") .AddOpenIdConnect("oidc", options => { options.Authority = "https://localhost:7001"; options.ClientId = "client"; options.MapInboundClaims = false; options.SaveTokens = true; }); builder.Services.AddAuthorization(options => { options.FallbackPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); }); builder.Services.AddAntDesign(); ConfigurationHelper.Initialize(builder.Configuration); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run();
已尝试的解决方案
- 向
_import.razor添加@attribute [Authorize] - 在Razor页面使用
@attribute [Authorize] - 在
MainLayout.razor中使用AuthorizeView和Authorized组件
可行解决方案
1. 完善前端通道登出的端点处理
在Blazor客户端的program.cs中添加一个专门处理前端通道登出的端点,同时通知Blazor Hub用户登出状态:
app.MapGet("/signout-oidc", async (HttpContext context) => { // 清除本地Cookie await context.SignOutAsync("cookies"); await context.SignOutAsync("oidc"); // 通知Blazor Hub所有该用户的连接登出 var hubContext = context.RequestServices.GetRequiredService<IHubContext<BlazorHub>>(); var userId = context.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value; if (!string.IsNullOrEmpty(userId)) { await hubContext.Clients.User(userId).SendAsync("UserLoggedOut"); } return Results.Redirect("/"); });
2. 在Blazor组件中监听登出通知
在MainLayout.razor中注入导航服务和Hub连接,监听登出事件并自动跳转:
@inject NavigationManager NavManager @inject HubConnection HubConnection @implements IAsyncDisposable @code { protected override async Task OnInitializedAsync() { // 监听Hub发送的登出消息 HubConnection.On("UserLoggedOut", () => { NavManager.NavigateTo("/authentication/login", forceLoad: true); }); await HubConnection.StartAsync(); } public async ValueTask DisposeAsync() { if (HubConnection is not null) { await HubConnection.DisposeAsync(); } } }
3. 优化OpenID Connect的登出事件配置
在Blazor客户端的OpenID Connect配置中补充登出回调逻辑:
.AddOpenIdConnect("oidc", options => { options.Authority = "https://localhost:7001"; options.ClientId = "client"; options.MapInboundClaims = false; options.SaveTokens = true; options.Events = new OpenIdConnectEvents { // 登出时传递IdTokenHint给SSO OnRedirectToIdentityProviderForSignOut = async context => { var idToken = await context.HttpContext.GetTokenAsync("id_token"); if (!string.IsNullOrEmpty(idToken)) { context.ProtocolMessage.IdTokenHint = idToken; } await Task.CompletedTask; }, // 登出回调后重定向到登录页 OnSignedOutCallbackRedirect = context => { context.Response.Redirect("/authentication/login"); context.HandleResponse(); return Task.CompletedTask; } }; });
4. 强化AuthorizeView的未授权处理
在MainLayout.razor的AuthorizeView中添加未授权模板,确保未登录状态下自动跳转:
<AuthorizeView> <Authorized> <!-- 已授权用户的页面内容 --> @Body </Authorized> <NotAuthorized> @{ NavManager.NavigateTo("/authentication/login", forceLoad: true); } </NotAuthorized> </AuthorizeView>
内容的提问来源于stack exchange,提问作者Thanh Nguyen
相关产品推荐
相关产品推荐

