Blazor Server中如何在LoginDisplay.razor获取扩展IdentityUser的FirstName属性
解决方案:在Blazor Server的LoginDisplay中访问自定义IdentityUser属性
问题核心
context.User是ClaimsPrincipal类型,默认仅包含ASP.NET Identity基础声明(如用户名、邮箱),自定义的FirstName/LastName不会自动注入到声明中,也无法直接将ClaimsPrincipal转换为MyProjectUser,因此直接访问会失败。以下提供两种可行方案:
方案一:通过UserManager直接获取用户实例(简单直接)
修改LoginDisplay.razor,注入UserManager<MyProjectUser>后查询完整用户对象:
@using Microsoft.AspNetCore.Identity @using MyProject.Data @inject UserManager<MyProjectUser> UserManager <CascadingAuthenticationState> <AuthorizeView> <Authorized> @{ var currentUser = await UserManager.GetUserAsync(context.User); } <a href="Identity/Account/Manage">Hello, @currentUser?.FirstName!</a> <form method="post" action="Identity/Account/Logout"> <button type="submit" class="nav-link btn btn-link">Log out</button> </form> </Authorized> <NotAuthorized> <a href="Identity/Account/Register">Register</a> <a href="Identity/Account/Login">Log in</a> </NotAuthorized> </AuthorizeView> </CascadingAuthenticationState>
注意:此方法每次渲染都会查询数据库,适合小型项目或低访问量场景。
方案二:将自定义属性注入Claims(高效推荐)
通过自定义ClaimsPrincipalFactory,把FirstName/LastName添加到用户声明中,后续无需重复查询数据库:
- 创建自定义声明工厂类
using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using System.Security.Claims; using MyProject.Data; namespace MyProject { public class CustomUserClaimsFactory : UserClaimsPrincipalFactory<MyProjectUser> { public CustomUserClaimsFactory(UserManager<MyProjectUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { } protected override async Task<ClaimsIdentity> GenerateClaimsAsync(MyProjectUser user) { var identity = await base.GenerateClaimsAsync(user); // 添加自定义属性到声明 if (!string.IsNullOrEmpty(user.FirstName)) { identity.AddClaim(new Claim(ClaimTypes.GivenName, user.FirstName)); } if (!string.IsNullOrEmpty(user.LastName)) { identity.AddClaim(new Claim(ClaimTypes.Surname, user.LastName)); } return identity; } } }
- 在
Program.cs中注册该工厂
找到AddDefaultIdentity的配置代码,追加注册自定义声明工厂:
builder.Services.AddDefaultIdentity<MyProjectUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<MyProjectContext>() .AddClaimsPrincipalFactory<CustomUserClaimsFactory>(); // 新增此行
- 在
LoginDisplay.razor中直接从声明读取属性
@using System.Security.Claims <CascadingAuthenticationState> <AuthorizeView> <Authorized> <a href="Identity/Account/Manage">Hello, @context.User.FindFirst(ClaimTypes.GivenName)?.Value!</a> <form method="post" action="Identity/Account/Logout"> <button type="submit" class="nav-link btn btn-link">Log out</button> </form> </Authorized> <NotAuthorized> <a href="Identity/Account/Register">Register</a> <a href="Identity/Account/Login">Log in</a> </NotAuthorized> </AuthorizeView> </CascadingAuthenticationState>
内容的提问来源于stack exchange,提问作者TrevorBrooks
相关产品推荐
相关产品推荐

