You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Identity Core获取Name字段及添加自定义字段方法咨询

ASP.NET Identity Core 自定义用户字段完全指南

兄弟,我来给你把Identity里的Name字段逻辑和自定义字段的实现讲得明明白白——完全不用改官方源码,在你自己的项目里就能搞定!

一、先搞懂Name字段的来龙去脉

首先得澄清:默认的IdentityUser实体类里并没有直接叫Name的字段!你代码里拿到的Name,99%是来自**身份声明(Claims)**里的ClaimTypes.Name,它本质上和IdentityUserUserName是绑定的:

  • 数据库层:IdentityUserUserName是存在AspNetUsers表的字段,还有个NormalizedUserName是用来做索引和查询优化的(比如全大写格式)。
  • 认证层:用户登录后,SignInManager会生成包含用户身份信息的票据,默认配置下,UserName会被自动映射到ClaimTypes.Name这个声明,所以你在HttpContext.User.Identity.Name里拿到的其实就是UserName的值——除非你自己改了声明生成逻辑。

二、添加自定义字段的实操步骤(零修改官方源码)

Identity的设计本身就支持扩展,核心思路就是继承官方的IdentityUser类,扩展自己的属性,再让EF Core和Identity服务适配这个自定义类

1. 定义你的自定义用户实体

创建一个继承自IdentityUser的类,把你要的MyCustomFieldAddress加进去——至于Id,官方已经自带了,默认是string类型(生成Guid字符串),如果要改成int/long,直接指定泛型参数就行:

// 用默认string类型Id的版本
public class ApplicationUser : IdentityUser
{
    // 自定义字段,按需添加
    public string? MyCustomField { get; set; }
    public string? Address { get; set; }
}

// 如果要改成int类型Id的版本
public class ApplicationUser : IdentityUser<int>
{
    public string? MyCustomField { get; set; }
    public string? Address { get; set; }
}

2. 更新你的DbContext

让项目里的DbContext继承IdentityDbContext<ApplicationUser>(如果改了Id类型,要对应改成IdentityDbContext<ApplicationUser, IdentityRole<int>, int>):

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    // 可选:用Fluent API给自定义字段加约束,比如长度、索引
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        
        // 示例:给Address字段设最大长度250
        builder.Entity<ApplicationUser>()
            .Property(u => u.Address)
            .HasMaxLength(250);
    }
}

3. 配置Identity服务

在Program.cs(或者老版本的Startup.cs)里注册Identity时,指定你的自定义用户类型:

// .NET 6+ 顶级语句写法
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

4. 更新数据库结构

打开终端或者Package Manager Console,执行迁移命令,把自定义字段同步到数据库:

# 生成迁移文件
Add-Migration AddCustomUserFields
# 把迁移应用到数据库
Update-Database

执行完后,你去看AspNetUsers表,就会多出来MyCustomFieldAddress这两列了!

5. 在代码里用自定义字段

创建用户的时候直接赋值:

var newUser = new ApplicationUser
{
    UserName = "jane.doe@example.com",
    Email = "jane.doe@example.com",
    MyCustomField = "我的自定义值",
    Address = "北京市朝阳区XX路XX号"
};
var createResult = await _userManager.CreateAsync(newUser, "StrongPass123!");

获取当前用户的自定义字段:

var currentUser = await _userManager.GetUserAsync(User);
if (currentUser != null)
{
    var customVal = currentUser.MyCustomField;
    var userAddress = currentUser.Address;
}

6. 把自定义字段加到身份声明里(可选)

如果你想在HttpContext.User里直接通过声明拿到自定义字段,可以自定义ClaimsPrincipalFactory,把字段加到声明集合里:

public class CustomUserClaimsFactory : UserClaimsPrincipalFactory<ApplicationUser>
{
    public CustomUserClaimsFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> options)
        : base(userManager, options)
    {
    }

    protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
    {
        var identity = await base.GenerateClaimsAsync(user);
        // 把自定义字段添加为声明
        if (!string.IsNullOrEmpty(user.MyCustomField))
        {
            identity.AddClaim(new Claim("MyCustomField", user.MyCustomField));
        }
        if (!string.IsNullOrEmpty(user.Address))
        {
            identity.AddClaim(new Claim("Address", user.Address));
        }
        return identity;
    }
}

然后在Program.cs里注册这个工厂:

builder.Services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomUserClaimsFactory>();

之后就可以用User.FindFirstValue("MyCustomField")直接获取值了!

三、核心原理唠两句

ASP.NET Identity是基于泛型和实体继承设计的,官方的IdentityUser只是一个基础模板,你继承它之后,EF Core会自动识别新增的属性并映射到数据库,而Identity的核心服务(UserManagerSignInManager)都是泛型实现的,能完美适配你的自定义用户类——这就是为啥不用改官方源码也能扩展的原因。

至于Id字段,官方默认用string(Guid)是为了分布式场景下的唯一性,如果你要改成数值型,只要在继承IdentityUser时指定泛型参数,再同步DbContext和迁移就行,Identity会自动处理主键的变化。


内容的提问来源于stack exchange,提问作者Bagzli

火山引擎 最新活动