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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:15:01