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

在.NET 8 Blazor Server项目中最小化集成ABP 8.3.4,配置ICurrentUser从外部ABP Identity实例获取用户角色与权限

在.NET 8 Blazor Server项目中最小化集成ABP 8.3.4,配置ICurrentUser从外部ABP Identity实例获取用户角色与权限

兄弟,你已经走对了大半路——OIDC跳转认证通了,就差把外部Identity服务返回的用户信息和ABP的ICurrentUser等核心服务打通了。我给你列几个最小改动的步骤,尽量不破坏你现有项目的结构:

1. 补充ABP核心身份模块依赖

ABP的ICurrentUser等服务由AbpIdentityAbstractionsModule提供,先把这个依赖加到你的模块类上:

[DependsOn(
    typeof(AbpAspNetCoreModule),
    typeof(AbpAutofacModule),
    typeof(AbpIdentityAbstractionsModule) // 新增:引入ABP身份抽象模块
)]
public class APPAbpModule : AbpModule
{
    // 你的现有代码...
}

2. 完善OIDC的Claim映射(关键!)

ABP的ICurrentUser是从ClaimsPrincipal中读取数据的,而外部ABP Identity服务返回的Claim名称需要和ABP的标准Claim类型对应。修改你OIDC的配置,添加Claim映射:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    context.Services
        .AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie("Cookies", options =>
        {
            options.ExpireTimeSpan = TimeSpan.FromDays(365);
        })
        .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
        {
            options.Authority = "https://localhost:44331";
            options.ClientId = "APP_Client";
            options.ClientSecret = "你的客户端密钥"; // 注意:Blazor Server建议用Confidential Client,这里要和Identity Server的配置一致
            options.CallbackPath = "/signin-oidc"; // 改成OIDC默认回调路径,要和Identity Server里的客户端RedirectUri匹配
            options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.ResponseType = OpenIdConnectResponseType.Code;
            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;
            options.RequireHttpsMetadata = true;
            options.MapInboundClaims = false; // 禁用自动映射,避免打乱ABP的Claim结构

            // 核心:把Identity Server返回的Claim映射到ABP标准Claim
            options.ClaimActions.MapUniqueJsonKey(AbpClaimTypes.UserId, "sub"); // ABP Identity的sub就是用户ID
            options.ClaimActions.MapUniqueJsonKey(AbpClaimTypes.UserName, "name");
            options.ClaimActions.MapUniqueJsonKey(AbpClaimTypes.Email, "email");
            // 如果返回的是角色数组,用MapJsonKey而不是MapUniqueJsonKey
            options.ClaimActions.MapJsonKey(AbpClaimTypes.Role, "roles", "role");
            // 如果你需要获取权限,添加这个映射(前提是Identity Server返回permissions数组)
            options.ClaimActions.MapJsonKey(AbpClaimTypes.Permission, "permissions", "permission");
        });

    // 新增:配置ABP使用的Claim类型
    context.Services.Configure<AbpIdentityOptions>(options =>
    {
        options.UserIdClaimType = AbpClaimTypes.UserId;
        options.UserNameClaimType = AbpClaimTypes.UserName;
        options.RoleClaimType = AbpClaimTypes.Role;
        options.PermissionClaimType = AbpClaimTypes.Permission;
    });

    // 新增:配置ABP权限从Claim中读取
    context.Services.Configure<PermissionOptions>(options =>
    {
        options.ValueProviders.Add<ClaimsPermissionValueProvider>();
    });

    // 新增:Blazor Server Circuit认证配置
    context.Services.AddServerSideBlazor(options =>
    {
        options.CircuitOptions.AuthenticationMode = AuthenticationMode.Authenticate;
    });
}

3. 确保Program.cs的中间件顺序正确

你的Module里注释了中间件代码,那Program.cs里要保证顺序不能乱(这是Blazor Server认证生效的关键):

var builder = WebApplication.CreateBuilder(args);

// 注册你的ABP模块
builder.Host.UseAutofac();
builder.Services.AddApplication<APPAbpModule>();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

// 必须先认证,再授权
app.UseAuthentication();
app.UseAuthorization();

app.UseBlazorFrameworkFiles();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

4. 检查外部ABP Identity Server的客户端配置

登录你的ABP Identity管理后台,找到APP_Client这个客户端,确认:

  • Allowed Grant Types:包含authorization_code
  • Redirect URIs:添加https://localhost:你的主项目端口/signin-oidc
  • Allowed Scopes:至少包含openid、profile、email、roles,如果要权限的话加上permissions
  • Client Secret:和你主项目里配置的一致(如果是Confidential Client)
  • Always Include User Claims in Id Token:开启,或者确保UserInfo端点能返回所需的Claim

5. Blazor组件的认证上下文配置

在_Host.cshtml里添加CascadingAuthenticationState,确保所有组件能拿到认证信息:

@page "/"
@namespace YourApp.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = null;
}

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- 你的现有头部代码 -->
</head>
<body>
    <!-- 新增:包裹认证上下文 -->
    <component type="typeof(CascadingAuthenticationState)" render-mode="ServerPrerendered">
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </component>

    <script src="_framework/blazor.server.js"></script>
</body>
</html>

然后在需要认证的组件里,你就可以正常注入ICurrentUser和IPermissionChecker了:

@inject ICurrentUser CurrentUser
@inject IPermissionChecker PermissionChecker
@attribute [Authorize]

<h3>用户信息</h3>
<p>已认证:@CurrentUser.IsAuthenticated</p>
<p>用户ID:@CurrentUser.Id</p>
<p>用户名:@CurrentUser.UserName</p>
<p>是否有某个权限:@(await PermissionChecker.IsGrantedAsync("你的权限名称"))</p>

最后提醒

  • 如果你不需要权限系统,可以跳过权限相关的映射和配置
  • 测试的时候,先清除浏览器缓存的Cookie,避免旧的认证信息干扰
  • 如果遇到Claim不显示的问题,可以在认证成功后打印User.Claims,检查返回的Claim是否正确映射

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:49:51