ASP.NET 8 Web API如何编辑Identity默认端点(不含MVC布局文件)
ASP.NET 8 Web API 自定义Identity登录端点的实用方案
方案一:手动编写API端点,复用Identity核心登录逻辑
既然你不想从头写复杂的登录验证(密码校验、账户锁定、双因素验证等),可以直接注入Identity的核心服务(SignInManager<TUser>、UserManager<TUser>),自定义InputModel后调用官方封装好的登录逻辑,完全不需要依赖MVC相关文件。
步骤示例:
- 定义自定义登录输入模型
public class CustomLoginInputModel { [Required] [EmailAddress] public string Email { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } // 按需添加你的扩展字段 public bool RememberMe { get; set; } = false; public string? ExtraUserInfo { get; set; } }
- 编写API控制器的登录方法
[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly SignInManager<ApplicationUser> _signInManager; private readonly UserManager<ApplicationUser> _userManager; public AuthController(SignInManager<ApplicationUser> signInManager, UserManager<ApplicationUser> userManager) { _signInManager = signInManager; _userManager = userManager; } [HttpPost("login")] public async Task<IActionResult> Login([FromBody] CustomLoginInputModel model) { if (!ModelState.IsValid) return BadRequest(ModelState); // 根据邮箱查询用户(用用户名登录就换FindByNameAsync) var user = await _userManager.FindByEmailAsync(model.Email); if (user == null) return Unauthorized("无效的登录凭据"); // 调用Identity核心登录逻辑,自动处理密码验证、账户锁定等 var signInResult = await _signInManager.CheckPasswordSignInAsync(user, model.Password, lockoutOnFailure: true); if (signInResult.Succeeded) { // 处理你的扩展字段逻辑,比如根据ExtraUserInfo更新用户属性 if (!string.IsNullOrEmpty(model.ExtraUserInfo)) { user.ExtraField = model.ExtraUserInfo; await _userManager.UpdateAsync(user); } // 登录成功,返回JWT或自定义响应(根据你的API需求) await _signInManager.SignInAsync(user, model.RememberMe); return Ok(new { UserId = user.Id, Message = "登录成功" }); } else if (signInResult.IsLockedOut) return Unauthorized("账户已锁定,请10分钟后重试"); else if (signInResult.IsNotAllowed) return Unauthorized("账户未激活,请先验证邮箱"); else return Unauthorized("密码错误"); } }
方案二:生成脚手架后清理冗余文件,保留核心逻辑
如果已经通过脚手架生成了登录相关文件,可以直接删除所有.cshtml、布局文件,只保留Login.cshtml.cs中的逻辑代码,将其改造为可复用的业务逻辑类,而非MVC页面模型。
改造示例:
- 删除所有
.cshtml文件,将Login.cshtml.cs修改为独立逻辑类:
public class LoginService { private readonly SignInManager<ApplicationUser> _signInManager; private readonly ILogger<LoginService> _logger; public LoginService(SignInManager<ApplicationUser> signInManager, ILogger<LoginService> logger) { _signInManager = signInManager; _logger = logger; } // 自定义InputModel,添加扩展字段 public class LoginInputModel { [Required] [EmailAddress] public string Email { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } public bool RememberMe { get; set; } public string? CustomField { get; set; } } public async Task<SignInResult> ExecuteLoginAsync(LoginInputModel model) { // 复用脚手架生成的核心登录逻辑 var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: true); if (result.Succeeded) { _logger.LogInformation("用户登录成功"); // 在这里处理你的扩展字段业务 } return result; } }
- 在API控制器中注入这个服务使用:
[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly LoginService _loginService; public AuthController(LoginService loginService) { _loginService = loginService; } [HttpPost("login")] public async Task<IActionResult> Login([FromBody] LoginService.LoginInputModel model) { if (!ModelState.IsValid) return BadRequest(ModelState); var result = await _loginService.ExecuteLoginAsync(model); // 处理登录结果并返回响应 if (result.Succeeded) return Ok("登录成功"); // 其他情况的返回逻辑... } }
方案三:使用Identity官方API端点,自定义扩展逻辑
ASP.NET 8支持直接启用Identity API端点,你可以通过自定义模型绑定或事件订阅来扩展登录逻辑,不需要手写完整端点。
配置示例:
- 在
Program.cs中启用Identity API:
builder.Services.AddIdentityApiEndpoints<ApplicationUser>() .AddEntityFrameworkStores<ApplicationDbContext>(); // 映射Identity API端点 app.MapIdentityApi<ApplicationUser>();
- 扩展登录请求模型:通过自定义绑定器将请求参数映射到包含扩展字段的模型,或者在登录事件中处理扩展逻辑:
// 订阅SignInManager的登录成功事件,处理扩展字段 builder.Services.AddScoped<SignInManager<ApplicationUser>>((sp) => { var signInManager = sp.GetRequiredService<SignInManager<ApplicationUser>>(); signInManager.SignedIn += async (sender, args) => { // args.User为当前登录用户,可直接操作扩展属性 var customData = HttpContext.Request.Form["CustomField"].ToString(); if (!string.IsNullOrEmpty(customData)) { args.User.CustomField = customData; await sp.GetRequiredService<UserManager<ApplicationUser>>().UpdateAsync(args.User); } }; return signInManager; });
内容的提问来源于stack exchange,提问作者D.Alkhovik
相关产品推荐
相关产品推荐

