.NET8 Identity如何保留其他默认端点仅移除默认注册接口?
问题场景
我正在学习.NET8并构建首个API,项目使用Identity.EntityFrameworkCore处理用户逻辑,自定义了User类扩展属性:
using Microsoft.AspNetCore.Identity; using System.ComponentModel.DataAnnotations; namespace Blog.Models.Entities { public class User : IdentityUser { [DataType(DataType.DateTime)] public DateTime? BirthDate { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } public byte[]? ProfilePicture { get; set; } public virtual ICollection<Article>? blogs { get; set; } } }
启用默认Identity API端点后,可访问/login、/register等接口,但默认注册接口仅支持邮箱和密码,无法传递自定义属性,因此我实现了自定义注册端点:
[HttpPost("register")] public async Task<IActionResult> Register(RegisterUserDto input) { var user = new User() { FirstName = input.FirstName, LastName = input.LastName, BirthDate = input.BirthDate, Email = input.Email, UserName = input.UserName, }; var result = await _userManager.CreateAsync(user, input.PasswordHash); if (result.Succeeded) return Ok("User created successfully"); return BadRequest("Error occured"); }
现在存在两个/register接口(默认+自定义),但如果移除Program.cs中以下代码:
builder.Services.AddIdentityCore<User>() .AddEntityFrameworkStores<AppDbContext>() .AddApiEndpoints();
和
app.MapIdentityApi<User>();
会同时删除/login、/refresh、/forgotPassword等需要保留的端点。请问是否可以仅移除默认注册接口,保留其他默认端点?
解决方案
有三种可行方式实现需求:
1. 覆盖默认注册端点(最简方案)
.NET路由系统中,控制器定义的端点优先级高于MapIdentityApi注册的端点。只要自定义注册端点路径也是/register,默认注册端点会被自动覆盖,不会出现两个接口。
若仍出现冲突,可给自定义端点设置更高优先级:
[HttpPost("register", Order = -1)] // Order值越小优先级越高 public async Task<IActionResult> Register(RegisterUserDto input) { // 你的代码逻辑 }
2. 过滤移除默认注册端点
调用MapIdentityApi<User>()后,通过Where精准过滤并移除默认注册端点:
var identityEndpoints = app.MapIdentityApi<User>(); // 定位并移除默认POST /register端点 identityEndpoints.Where(e => e.Name == "Register" && e.Metadata.GetMetadata<HttpMethodMetadata>()?.HttpMethods.Contains("POST") == true) .ToList() .ForEach(e => e.Dispose());
3. 手动映射所需Identity端点(最灵活)
放弃MapIdentityApi<User>()一键注册所有端点,手动添加需要的端点(登录、刷新、忘记密码等),跳过注册端点。示例:
// 手动注册登录端点 app.MapPost("/login", async ( [FromBody] LoginRequest request, [FromServices] SignInManager<User> signInManager, [FromServices] ILogger<Program> logger) => { var result = await signInManager.PasswordSignInAsync(request.Email, request.Password, false, lockoutOnFailure: false); if (!result.Succeeded) { logger.LogWarning("Invalid login attempt for {Email}", request.Email); return Results.Unauthorized(); } var user = await signInManager.UserManager.FindByEmailAsync(request.Email); var token = await signInManager.UserManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, "Login"); return Results.Ok(new { Token = token }); }); // 按需手动添加/refresh、/forgotPassword等端点,逻辑可参考Identity官方源码实现
这种方式完全可控,但需自行实现部分端点逻辑,适合深度定制场景。
内容的提问来源于stack exchange,提问作者Selim Bamri
相关产品推荐
相关产品推荐

