在.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
相关产品推荐
相关产品推荐

