如何自定义.NET 8 Identity路由:扩展MapIdentityApi注册登录端点
解决方案
一、扩展/register和/login端点支持用户名
1. 自定义注册请求模型
创建包含独立用户名字段的注册请求类:
public class CustomRegisterRequest { [Required] public string Username { get; set; } = string.Empty; [Required] [EmailAddress] public string Email { get; set; } = string.Empty; [Required] [DataType(DataType.Password)] public string Password { get; set; } = string.Empty; }
2. 替换默认/register端点
在Program.cs中手动映射自定义注册逻辑,替代默认的IdentityApi注册端点:
// 保留IdentityApi基础服务配置(使用你扩展的AppUser类) builder.Services.AddIdentityApiEndpoints<AppUser>() .AddEntityFrameworkStores<AppDbContext>(); // 自定义注册端点 app.MapPost("/register", async (CustomRegisterRequest request, UserManager<AppUser> userManager) => { var user = new AppUser { UserName = request.Username, // 手动设置用户名,不再复用邮箱 Email = request.Email // 此处可直接赋值你的扩展字段,比如 FullName = request.FullName }; var createResult = await userManager.CreateAsync(user, request.Password); if (!createResult.Succeeded) { return Results.BadRequest(createResult.Errors); } // 可选:生成邮箱确认令牌并发送邮件 var confirmToken = await userManager.GenerateEmailConfirmationTokenAsync(user); // 邮件发送逻辑自行实现 return Results.Ok(new { UserId = user.Id }); }) .AllowAnonymous();
3. 让/login支持用户名登录
创建支持用户名/邮箱双输入的登录请求类,并自定义登录逻辑:
public class CustomLoginRequest { [Required] public string LoginId { get; set; } = string.Empty; // 可传入用户名或邮箱 [Required] [DataType(DataType.Password)] public string Password { get; set; } = string.Empty; public bool RememberMe { get; set; } }
映射自定义登录端点:
app.MapPost("/login", async (CustomLoginRequest request, SignInManager<AppUser> signInManager) => { // 先尝试按邮箱查找,再按用户名查找 var user = await signInManager.UserManager.FindByEmailAsync(request.LoginId) ?? await signInManager.UserManager.FindByNameAsync(request.LoginId); if (user == null) { return Results.Unauthorized(); } // 验证密码并生成令牌 var signInResult = await signInManager.CheckPasswordSignInAsync(user, request.Password, request.RememberMe); if (!signInResult.Succeeded) { return Results.Unauthorized(); } var accessToken = await signInManager.CreateUserTokenAsync(user, "Identity.Application", "AccessToken"); return Results.Ok(new { AccessToken = accessToken }); }) .AllowAnonymous();
二、扩展IdentityUser字段后更新端点
默认IdentityApi端点使用内置模型,不会自动包含扩展字段,需手动修改请求/响应逻辑:
1. 注册时保存扩展字段
在CustomRegisterRequest中添加扩展字段:
public class CustomRegisterRequest { // 原有Username、Email、Password字段 [Required] public string FullName { get; set; } = string.Empty; [Phone] public string PhoneNumber { get; set; } = string.Empty; }
在注册逻辑中赋值扩展字段:
var user = new AppUser { UserName = request.Username, Email = request.Email, FullName = request.FullName, PhoneNumber = request.PhoneNumber };
2. 修改端点返回包含扩展字段
自定义用户信息响应模型,并覆盖默认的/me端点:
public class UserResponse { public string Id { get; set; } = string.Empty; public string Username { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; public bool EmailConfirmed { get; set; } // 添加你的扩展字段 public string FullName { get; set; } = string.Empty; public string PhoneNumber { get; set; } = string.Empty; }
映射自定义/me端点:
app.MapGet("/me", async (ClaimsPrincipal user, UserManager<AppUser> userManager) => { var appUser = await userManager.GetUserAsync(user); if (appUser == null) { return Results.Unauthorized(); } return Results.Ok(new UserResponse { Id = appUser.Id, Username = appUser.UserName!, Email = appUser.Email!, EmailConfirmed = appUser.EmailConfirmed, FullName = appUser.FullName, PhoneNumber = appUser.PhoneNumber! }); }) .RequireAuthorization();
内容的提问来源于stack exchange,提问作者noahkriesi
相关产品推荐
相关产品推荐

