如何在Blazor WebAssembly项目中配置多OIDC(Keycloak多Realm)认证
解决Blazor WebAssembly多Keycloak Realm认证问题
你当前的问题是因为AddOidcAuthentication默认只会注册一个认证方案,后续的配置绑定会覆盖之前的。要支持多个Keycloak Realm,需要为每个Realm单独配置认证方案,并自定义登录选择逻辑。
步骤1:修正配置文件错误
首先修正appsettings.json中t2的Authority配置(你之前写错成了t1的Realm):
{ "t1": { "Authority": "http://localhost:8080/realms/t1", "ClientId": "client" }, "t2": { "Authority": "http://localhost:8080/realms/t2", "ClientId": "client" } }
步骤2:配置多个OIDC认证方案
修改Program.cs,为每个Realm注册独立的认证方案(指定Scheme名称):
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using BlazorApp4; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); // 注册Realm t1的认证方案 builder.Services.AddOidcAuthentication("t1", options => { builder.Configuration.Bind("t1", options.ProviderOptions); options.ProviderOptions.ResponseType = "code"; options.ProviderOptions.RedirectUri = "authentication/login-callback"; options.ProviderOptions.PostLogoutRedirectUri = "authentication/logout-callback"; }); // 注册Realm t2的认证方案 builder.Services.AddOidcAuthentication("t2", options => { builder.Configuration.Bind("t2", options.ProviderOptions); options.ProviderOptions.ResponseType = "code"; options.ProviderOptions.RedirectUri = "authentication/login-callback"; options.ProviderOptions.PostLogoutRedirectUri = "authentication/logout-callback"; }); builder.Services.AddScoped<AuthenticationStateProvider>(sp => sp.GetRequiredService<RemoteAuthenticationStateProvider<RemoteUserAccount>>()); await builder.Build().RunAsync();
步骤3:自定义登录选择页面
修改Authentication.razor,让用户可以选择要登录的Realm,并触发对应方案的认证流程:
@page "/authentication/{action}" @using Microsoft.AspNetCore.Components.WebAssembly.Authentication @inject NavigationManager NavManager @inject IRemoteAuthenticationService<RemoteAuthenticationState, RemoteUserAccount> AuthService @if (Action?.ToLower() == "login") { <div style="padding: 2rem; max-width: 400px; margin: 0 auto;"> <h3>选择登录的Realm</h3> <div style="margin-top: 1rem; display: flex; gap: 1rem;"> <button class="btn btn-primary" @onclick="() => LoginWithScheme("t1")">登录到Realm t1</button> <button class="btn btn-secondary" @onclick="() => LoginWithScheme("t2")">登录到Realm t2</button> </div> </div> } else { <RemoteAuthenticatorView Action="@Action" /> } @code { [Parameter] public string? Action { get; set; } private async Task LoginWithScheme(string scheme) { var authContext = new RemoteAuthenticationContext<RemoteAuthenticationState> { Scheme = scheme, ReturnUrl = NavManager.Uri }; var result = await AuthService.LoginAsync(authContext); if (!result.Succeeded) { // 这里可以添加登录失败的提示逻辑 Console.WriteLine($"登录失败:{result.Error}"); } } }
步骤4:Keycloak客户端配置
确保每个Keycloak Realm下的客户端都添加了正确的Valid Redirect URIs,比如你的Blazor应用地址加上/authentication/login-callback,例如:http://localhost:5000/authentication/login-callback
额外:注销时指定Scheme
如果需要注销,也要对应指定Scheme,比如在组件中添加注销逻辑:
private async Task LogoutWithCurrentScheme(string scheme) { var authContext = new RemoteAuthenticationContext<RemoteAuthenticationState> { Scheme = scheme, ReturnUrl = "/" }; await AuthService.LogoutAsync(authContext); }
内容的提问来源于stack exchange,提问作者jhen
相关产品推荐
相关产品推荐

