如何在ASP.NET Core Web API Identity用户注册时添加额外字段
解决方案
1. 修正Identity映射与DbContext配置
你当前代码里存在两个问题:一是MapIdentityApi<IdentityUser>使用了默认用户类,和自定义的UserEntity不匹配;二是重复添加了DbContext实例。先修正这两处:
// 移除内存数据库的DbContext配置,保留PostgreSQL的配置 builder.Services.AddDbContext<QuiltDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); // 将MapIdentityApi的泛型参数改为自定义的UserEntity app.MapGroup("/my-identity-api").MapIdentityApi<UserEntity>();
2. 创建注册请求DTO
定义包含所有必填字段的DTO,用于接收前端的注册参数:
using System.ComponentModel.DataAnnotations; namespace Quilt.Models.DTOs { public class RegisterRequest { [Required] [EmailAddress] public string Email { get; set; } [Required] [MinLength(6)] public string Password { get; set; } [Required] public string FirstName { get; set; } [Required] public string LastName { get; set; } [Required] [DataType(DataType.Date)] public DateTime Birthday { get; set; } public string? Avatar { get; set; } [Required] public string Gender { get; set; } } }
3. 自定义注册端点
默认的MapIdentityApi提供的注册接口只支持邮箱和密码,因此需要自定义注册端点,借助Identity的UserManager完成用户创建与额外字段赋值:
app.MapPost("/my-identity-api/register", async ( [FromBody] RegisterRequest request, UserManager<UserEntity> userManager, SignInManager<UserEntity> signInManager) => { // 验证DTO参数合法性 var validationResults = new List<ValidationResult>(); if (!Validator.TryValidateObject(request, new ValidationContext(request), validationResults, validateAllProperties: true)) { return Results.ValidationProblem(validationResults.ToDictionary( v => v.MemberNames.FirstOrDefault() ?? string.Empty, v => new[] { v.ErrorMessage })); } // 实例化自定义用户类并赋值额外字段 var user = new UserEntity { UserName = request.Email, Email = request.Email, FirstName = request.FirstName, LastName = request.LastName, Birthday = request.Birthday, Avatar = request.Avatar, Gender = request.Gender }; // 调用Identity核心方法创建用户(自动处理密码哈希) var createResult = await userManager.CreateAsync(user, request.Password); if (!createResult.Succeeded) { return Results.BadRequest(createResult.Errors.Select(e => new { e.Code, e.Description })); } // 注册成功后直接生成Bearer Token(可选,若不需要可跳过此段) var accessToken = await signInManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, "Bearer"); return Results.Ok(new { AccessToken = accessToken }); }) .WithName("CustomRegister") .WithOpenApi();
4. 完整修正后的Program.cs示例
using System.Security.Claims; using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Quilt.DataAccess.Data; using Quilt.Models.User; var builder = WebApplication.CreateBuilder(args); // 配置DbContext builder.Services.AddDbContext<QuiltDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); // 配置认证与授权 builder.Services.AddAuthentication().AddBearerToken(IdentityConstants.BearerScheme); builder.Services.AddAuthorizationBuilder(); // 配置自定义Identity用户 builder.Services.AddIdentityCore<UserEntity>() .AddEntityFrameworkStores<QuiltDbContext>() .AddApiEndpoints() .AddDefaultTokenProviders(); // 配置Swagger builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // 映射Identity基础接口(登录、token刷新等) app.MapGroup("/my-identity-api").MapIdentityApi<UserEntity>(); // 自定义注册接口 app.MapPost("/my-identity-api/register", async ( [FromBody] RegisterRequest request, UserManager<UserEntity> userManager, SignInManager<UserEntity> signInManager) => { var validationResults = new List<ValidationResult>(); if (!Validator.TryValidateObject(request, new ValidationContext(request), validationResults, validateAllProperties: true)) { return Results.ValidationProblem(validationResults.ToDictionary( v => v.MemberNames.FirstOrDefault() ?? string.Empty, v => new[] { v.ErrorMessage })); } var user = new UserEntity { UserName = request.Email, Email = request.Email, FirstName = request.FirstName, LastName = request.LastName, Birthday = request.Birthday, Avatar = request.Avatar, Gender = request.Gender }; var createResult = await userManager.CreateAsync(user, request.Password); if (!createResult.Succeeded) { return Results.BadRequest(createResult.Errors.Select(e => new { e.Code, e.Description })); } var accessToken = await signInManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, "Bearer"); return Results.Ok(new { AccessToken = accessToken }); }) .WithName("CustomRegister") .WithOpenApi(); // 测试授权接口 app.MapGet("/", (ClaimsPrincipal user) => $"Hello {user.Identity!.Name}").RequireAuthorization(); // 开发环境启用Swagger if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.Run(); // 注册请求DTO定义(可单独放到类文件中) public class RegisterRequest { [Required] [EmailAddress] public string Email { get; set; } [Required] [MinLength(6)] public string Password { get; set; } [Required] public string FirstName { get; set; } [Required] public string LastName { get; set; } [Required] [DataType(DataType.Date)] public DateTime Birthday { get; set; } public string? Avatar { get; set; } [Required] public string Gender { get; set; } }
核心说明
- 全程复用ASP.NET Core Identity的核心组件(
UserManager、SignInManager),保证认证逻辑的安全性与规范性; - 自定义DTO实现前端参数的接收与验证,避免直接暴露实体类;
- 可选择在注册后直接返回Bearer Token,简化前端流程,也可仅返回注册成功提示,让用户后续走登录流程。
内容的提问来源于stack exchange,提问作者Julia
相关产品推荐
相关产品推荐

