ASP.NET Core为IdentityUserClaim添加自定义属性后UserManager无法读取的问题
问题核心
业务场景
需要对用户持有的声明做来源追踪标记,区分两类来源:一类是本地配置添加到用户账户的声明,一类是从第三方身份认证系统同步获取的远程声明,同一用户可同时持有两类来源的声明。
当前实现与卡点
- 已完成基础实体改造:继承
IdentityUserClaim<string>自定义了持久化用的声明实体,新增LocalClaim布尔属性做来源标记,可正常完成数据库层的读写,实体代码为:
public class UserClaim : IdentityUserClaim<string> { public bool LocalClaim { get; set; } }
- 链路卡点:
- 调用
var claim = userManager.GetClaimsAsync(user)获取用户声明时,返回对象为System.Security.Claims.Claim类型,无法读取对应声明绑定的LocalClaim自定义属性 - 调用
await userManager.AddClaimsAsync(user, claims)添加声明时,没有入口设置LocalClaim属性的取值
- 调用
- 核心诉求:打通
UserManager操作链路对自定义声明属性的访问能力,实现可读取指定声明对应的来源标记值。
解决方案
首先明确内置方法的设计边界:
UserManager提供的GetClaimsAsync、AddClaimsAsync是面向通用Claim类型的兼容操作,设计上不会返回或操作用户自定义扩展的IdentityUserClaim派生实体,无法访问自定义属性是默认设计行为,不是代码故障。
- 写入阶段打通自定义属性设置:
- 先调用内置
AddClaimsAsync方法完成基础声明信息的数据库写入 - 通过注入的
ApplicationDbContext查询对应用户ID的声明记录,匹配对应ClaimType、ClaimValue的条目 - 直接给匹配条目的
LocalClaim属性赋值,调用SaveChangesAsync完成持久化,完成自定义属性的写入
- 先调用内置
- 读取阶段打通自定义属性访问:
- 弃用内置
GetClaimsAsync的返回结果直接做业务判断的逻辑,在数据层直接查询UserClaims表,把基础声明信息(类型、值、颁发方)和LocalClaim字段映射组装为带来源标记的自定义返回对象 - 可把这套查询逻辑封装为
UserManager的扩展方法,比如实现GetClaimsWithSourceAsync方法,在所有需要读取声明的业务场景统一替换调用,避免在业务层重复写匹配逻辑
- 弃用内置
- 可选适配认证管道优化:如果需要在授权校验流程中直接读取来源标记,可在应用Cookie生成事件、自定义
ClaimsTransformer组件里,把数据库查出的LocalClaim值作为内置Claim对象的自定义属性写入,让认证管道在不回查数据库的前提下也能读取到来源标记。
内容的提问来源于stack exchange,提问作者Ihtsham Minhas
相关产品推荐
相关产品推荐

