ASP.NET Core Identity 使用方法:如何通过唯一邮箱查询目标用户?
ASP.NET Core Identity 基于唯一邮箱查询当前用户解决方案
原有报错原因:默认配置下ASP.NET Core Identity会把用户名存入Cookie的
Name声明,而你的业务场景中用户名不唯一,调用按用户名查询的方法时会匹配到多个用户触发错误。
你可以通过修改声明写入逻辑,将唯一的邮箱字段存入Cookie的声明中,后续直接用邮箱查询用户即可,具体实现步骤如下:
步骤1:配置自定义声明工厂
首先在Program.cs中注册自定义的声明工厂,替换默认的声明生成逻辑:
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>() // 注册自定义声明工厂 .AddClaimsPrincipalFactory<CustomUserClaimsPrincipalFactory>();
步骤2:实现CustomUserClaimsPrincipalFactory类
新建自定义声明工厂类,将邮箱写入Cookie声明:
using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using System.Security.Claims; public class CustomUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<IdentityUser> { public CustomUserClaimsPrincipalFactory(UserManager<IdentityUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { } protected override async Task<ClaimsIdentity> GenerateClaimsAsync(IdentityUser user) { var identity = await base.GenerateClaimsAsync(user); // 替换原有Name声明的取值为唯一邮箱,后续可直接通过User.Identity.Name读取邮箱 identity.RemoveClaim(identity.FindFirst(ClaimTypes.Name)); identity.AddClaim(new Claim(ClaimTypes.Name, user.Email)); return identity; } }
步骤3:按邮箱查询当前用户
后续查询用户时直接用User.Identity.Name拿到唯一邮箱,调用FindByEmailAsync查询即可,不会出现多匹配报错:
// 注入UserManager private readonly UserManager<IdentityUser> _userManager; public YourController(UserManager<IdentityUser> userManager) { _userManager = userManager; } public async Task<IActionResult> YourAction() { var userEmail = User.Identity?.Name; if (string.IsNullOrEmpty(userEmail)) { // 处理未登录逻辑 return Unauthorized(); } // 用唯一邮箱查询用户,无冲突 var currentUser = await _userManager.FindByEmailAsync(userEmail); // 后续业务逻辑 return Ok(currentUser); }
可选实现:保留原有用户名的Name声明
如果不想修改原有User.Identity.Name返回用户名的逻辑,可以单独新增邮箱声明,单独读取:
- 声明工厂中新增代码:
// 不修改原有Name声明,单独添加邮箱声明 identity.AddClaim(new Claim("UniqueUserEmail", user.Email));
- 查询时读取该声明:
var userEmail = User.FindFirstValue("UniqueUserEmail"); var currentUser = await _userManager.FindByEmailAsync(userEmail);
内容的提问来源于stack exchange,提问作者Hossein
相关产品推荐
相关产品推荐

