如何在React & ASP.NET Core项目中自定义Identity实现短信与邮件功能?
自定义ASP.NET Core Identity API以集成短信/邮件功能
当默认Identity API无法满足短信、邮件集成的自定义需求时,可通过以下步骤手动扩展实现:
1. 替换默认Identity API端点
默认AddIdentityApiEndpoints封装的固定接口无法直接修改,需手动接管:
- 移除Program.cs中
builder.Services.AddIdentityApiEndpoints<IdentityUser>()及app.MapIdentityApi<IdentityUser>()的调用。 - 创建自定义认证控制器(如
AccountController),自行实现注册、邮箱验证、密码重置等核心流程。
2. 实现邮件/短信发送服务
先定义统一发送接口,再完成具体发送逻辑:
定义发送接口
public interface IEmailSender { Task SendEmailAsync(string email, string subject, string htmlMessage); } public interface ISmsSender { Task SendSmsAsync(string phoneNumber, string message); }
实现邮件发送服务(SMTP示例)
public class EmailSender : IEmailSender { private readonly IConfiguration _configuration; public EmailSender(IConfiguration configuration) { _configuration = configuration; } public async Task SendEmailAsync(string email, string subject, string htmlMessage) { using var client = new SmtpClient(_configuration["Smtp:Host"], int.Parse(_configuration["Smtp:Port"])) { Credentials = new NetworkCredential(_configuration["Smtp:Username"], _configuration["Smtp:Password"]), EnableSsl = bool.Parse(_configuration["Smtp:EnableSsl"]) }; var message = new MailMessage(_configuration["Smtp:From"], email, subject, htmlMessage) { IsBodyHtml = true }; await client.SendMailAsync(message); } }
注册服务到DI容器
在Program.cs中添加:
builder.Services.AddScoped<IEmailSender, EmailSender>(); builder.Services.AddScoped<ISmsSender, SmsSender>(); // 替换为你的短信实现类
3. 集成到用户认证流程
在自定义AccountController中注入UserManager<IdentityUser>和发送服务,处理关键流程:
注册并发送邮箱验证邮件
[ApiController] [Route("api/[controller]")] public class AccountController : ControllerBase { private readonly UserManager<IdentityUser> _userManager; private readonly IEmailSender _emailSender; public AccountController(UserManager<IdentityUser> userManager, IEmailSender emailSender) { _userManager = userManager; _emailSender = emailSender; } [HttpPost("register")] public async Task<IActionResult> Register(RegisterModel model) { var user = new IdentityUser { UserName = model.Email, Email = model.Email }; var result = await _userManager.CreateAsync(user, model.Password); if (result.Succeeded) { var token = await _userManager.GenerateEmailConfirmationTokenAsync(user); var confirmationLink = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, token }, protocol: HttpContext.Request.Scheme); await _emailSender.SendEmailAsync(model.Email, "确认你的邮箱", $"请点击链接确认邮箱:<a href='{confirmationLink}'>确认</a>"); return Ok("注册成功,请查收邮件完成验证"); } return BadRequest(result.Errors); } [HttpGet("confirm-email")] public async Task<IActionResult> ConfirmEmail(string userId, string token) { var user = await _userManager.FindByIdAsync(userId); if (user == null) return NotFound(); var result = await _userManager.ConfirmEmailAsync(user, token); return result.Succeeded ? Ok("邮箱验证成功") : BadRequest("验证失败"); } [HttpPost("forgot-password")] public async Task<IActionResult> ForgotPassword(ForgotPasswordModel model) { var user = await _userManager.FindByEmailAsync(model.Email); if (user != null && await _userManager.IsEmailConfirmedAsync(user)) { var token = await _userManager.GeneratePasswordResetTokenAsync(user); var resetLink = Url.Action("ResetPassword", "Account", new { email = model.Email, token }, protocol: HttpContext.Request.Scheme); await _emailSender.SendEmailAsync(model.Email, "重置你的密码", $"请点击链接重置密码:<a href='{resetLink}'>重置</a>"); // 如需短信验证,替换为调用ISmsSender发送含token的短信 } return Ok("如果你的邮箱存在,我们已发送重置链接"); } }
4. 配置Identity选项
在Program.cs中配置令牌相关规则:
builder.Services.AddDefaultIdentity<IdentityUser>(options => { options.SignIn.RequireConfirmedAccount = true; options.Tokens.EmailConfirmationTokenProvider = "EmailConfirmation"; }) .AddTokenProvider<DataProtectorTokenProvider<IdentityUser>>("EmailConfirmation") .AddEntityFrameworkStores<ApplicationDbContext>(); // 自定义令牌有效期 builder.Services.Configure<DataProtectionTokenProviderOptions>(options => { options.TokenLifespan = TimeSpan.FromHours(2); // 邮箱验证令牌2小时有效 });
5. 前端适配自定义API
修改React前端的请求逻辑,将原默认Identity API的调用地址,替换为自定义的/api/account/register、/api/account/forgot-password等端点。
内容的提问来源于stack exchange,提问作者hmahdavi
相关产品推荐
相关产品推荐

