如何使用ASP.NET Core Identity的ProtectedPersonalData特性加密自定义用户属性
问题原因
ASP.NET Core Identity 默认的UserStore仅会扫描IdentityUser基类标记了[ProtectedPersonalData]的属性,自定义子类的属性不会被自动识别,因此不会触发加密逻辑,这就是你没有进入对应Protect方法的原因。
解决步骤
1. 注册自定义保护实现
你需要先将自定义的三个保护服务注册到依赖注入容器,否则你的实现不会被Identity调用:
// 新增到Program.cs/Startup.cs的服务注册逻辑中,放在AddIdentity配置之前 services.AddSingleton<ILookupProtectorKeyRing, KeyRing>(); services.AddSingleton<ILookupProtector, Lookup>(); services.AddSingleton<IPersonalDataProtector, Protector>();
2. 自定义UserStore覆盖属性扫描逻辑
创建自定义的UserStore类,重写属性扫描方法,包含子类的自定义属性:
using System.Reflection; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; public class ApplicationUserStore : UserStore<ApplicationUser, IdentityRole, ApplicationDbContext, string> { public ApplicationUserStore( ApplicationDbContext context, IPersonalDataProtector protector, ILookupProtectorKeyRing keyRing, ILookupProtector lookupProtector, IdentityErrorDescriber describer = null) : base(context, protector, keyRing, lookupProtector, describer) { } protected override IEnumerable<PropertyInfo> GetPersonalDataProperties() { // 保留基类原有需要加密的属性 var baseProperties = base.GetPersonalDataProperties(); // 扫描当前ApplicationUser类中标记了ProtectedPersonalData特性的自定义属性 var customProperties = typeof(ApplicationUser) .GetProperties(BindingFlags.Instance | BindingFlags.Public) .Where(p => p.IsDefined(typeof(ProtectedPersonalDataAttribute), inherit: false)); return baseProperties.Concat(customProperties).Distinct(); } }
3. 替换Identity的默认UserStore
修改你的Identity注册配置,指定使用自定义的UserStore:
services.AddDefaultIdentity<ApplicationUser>(options => { options.Stores.ProtectPersonalData = true; }) .AddRoles<IdentityRole>() .AddUserStore<ApplicationUserStore>() // 替换默认UserStore .AddEntityFrameworkStores<ApplicationDbContext>();
效果验证
修改完成后,调用UserManager.CreateAsync新增用户、或者调用UserManager.UpdateAsync更新用户信息时,MyProperty字段会自动触发你实现的Protect方法加密后存入数据库;读取用户信息时会自动调用Unprotect方法解密,业务层无需额外处理。
内容的提问来源于stack exchange,提问作者Andrea Perelli
相关产品推荐
相关产品推荐

