ASP.NET5 Web API中使用Microsoft Identity获取扩展用户声明表中符合条件的声明
实现方案
你可以通过替换_signInManager依赖的默认用户声明工厂来实现需求,不需要修改原有CreateAsync的调用逻辑,也可以选择直接查询扩展声明表按需筛选,两种方式具体实现如下:
方案1:自定义声明工厂(适配_signinManager原生调用)
前置准备
首先确认你已经正确扩展了用户声明实体,示例结构如下:
// 自定义扩展用户声明实体,继承Identity默认实现 public class ExtendedUserClaim : IdentityUserClaim<string> { // 你新增的筛选字段 public bool IsSelected { get; set; } }
同时已在项目DbContext中完成扩展实体映射:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 绑定自定义声明实体到对应的表 modelBuilder.Entity<ExtendedUserClaim>(b => { b.HasKey(uc => uc.Id); b.ToTable("AspNetUserClaims"); // 替换为你实际的声明表名 }); }
重写声明生成逻辑
继承默认的UserClaimsPrincipalFactory,重写声明获取方法,过滤IsSelected = true的声明:
public class CustomUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<IdentityUser, IdentityRole> { private readonly YourDbContext _dbContext; // 注入依赖 public CustomUserClaimsPrincipalFactory( UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager, IOptions<IdentityOptions> optionsAccessor, YourDbContext dbContext) : base(userManager, roleManager, optionsAccessor) { _dbContext = dbContext; } protected override async Task<IEnumerable<Claim>> GetClaimsAsync(IdentityUser user) { // 保留默认生成的基础声明(比如用户名、用户ID等) var baseClaims = await base.GetClaimsAsync(user); // 从扩展表查询筛选仅IsSelected=true的自定义声明 var filteredClaims = await _dbContext.Set<ExtendedUserClaim>() .Where(c => c.UserId == user.Id && c.IsSelected) .Select(c => new Claim(c.ClaimType, c.ClaimValue)) .ToListAsync(); // 合并基础声明和筛选后的自定义声明,避免重复 return baseClaims .Where(c => !filteredClaims.Select(f => f.Type).Contains(c.Type)) .Concat(filteredClaims); } }
替换默认服务注册
在服务注册逻辑中替换Identity默认的声明工厂:
- 如果你用.NET 5的
Startup.cs,在ConfigureServices方法中添加:
services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<YourDbContext>() // 替换默认声明工厂为自定义实现 .AddClaimsPrincipalFactory<CustomUserClaimsPrincipalFactory>();
- 如果你用.NET 6+的
Program.cs,直接在builder.Services配置中添加即可。
配置完成后,你原来的调用await _signInManager.ClaimsFactory.CreateAsync(user)返回的ClaimsPrincipal就只会包含IsSelected=true的声明。
方案2:直接查询筛选(轻量实现,无需修改Identity配置)
如果你只在少数场景需要筛选声明,不需要全局生效,可以直接查询扩展声明表按需获取:
// userId为目标用户的ID var selectedClaims = await _dbContext.Set<ExtendedUserClaim>() .Where(c => c.UserId == userId && c.IsSelected) .Select(c => new Claim(c.ClaimType, c.ClaimValue)) .ToListAsync();
内容的提问来源于stack exchange,提问作者Amir Masoud Babaei
相关产品推荐
相关产品推荐

