You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core注册时分离用户名与邮箱的实现方案咨询

Great call separating username and email—it’s a solid move for account security, as it prevents attackers from guessing a user’s login identifier just by knowing their email. Let’s break down multiple practical approaches to implement this in your ASP.NET Core Register action, building on the default code you shared.

方案1:基础分离实现(最直接的路径)

This is the minimal change to split username and email fields:

  • Update the RegisterViewModel: Add a dedicated UserName property with validation rules to enforce format and length.
    public class RegisterViewModel
    {
        [Required]
        [Display(Name = "用户名")]
        [StringLength(20, MinimumLength = 3, ErrorMessage = "用户名长度必须在3到20个字符之间")]
        [RegularExpression(@"^[a-zA-Z0-9_]+$", ErrorMessage = "用户名只能包含字母、数字和下划线")]
        public string UserName { get; set; }
    
        [Required]
        [EmailAddress]
        [Display(Name = "邮箱")]
        public string Email { get; set; }
    
        // 保留原有的密码、确认密码字段
        [Required]
        [StringLength(100, ErrorMessage = "{0} 长度至少为 {2} 个字符", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "密码")]
        public string Password { get; set; }
    
        [DataType(DataType.Password)]
        [Display(Name = "确认密码")]
        [Compare("Password", ErrorMessage = "密码与确认密码不匹配")]
        public string ConfirmPassword { get; set; }
    }
    
  • Modify the registration view: Add a new input field for the username, right alongside the email field.
    <div class="form-group">
        <label asp-for="UserName" class="control-label"></label>
        <input asp-for="UserName" class="form-control" />
        <span asp-validation-for="UserName" class="text-danger"></span>
    </div>
    
  • Adjust the Register action logic: Map the new UserName field to the ApplicationUser instead of reusing the email.
    public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            // 关键:不再将Email赋值给UserName
            var user = new ApplicationUser 
            { 
                UserName = model.UserName, 
                Email = model.Email 
            };
            var result = await _userManager.CreateAsync(user, model.Password);
            
            // 保留原有的成功/失败处理逻辑
            if (result.Succeeded)
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl ?? Url.Content("~/"));
            }
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }
        return View(model);
    }
    

方案2:增强唯一性与验证逻辑

To make this more robust, add checks to ensure both username and email are unique, and enforce stricter validation:

  • Enable unique email enforcement: In your Identity configuration (Program.cs/Startup.cs), set RequireUniqueEmail = true to prevent multiple accounts using the same email.
    builder.Services.AddDefaultIdentity<ApplicationUser>(options => 
    {
        options.SignIn.RequireConfirmedAccount = true;
        options.User.RequireUniqueEmail = true; // 启用邮箱唯一性
        options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; // 限制用户名允许的字符
    })
    .AddEntityFrameworkStores<ApplicationDbContext>();
    
  • Add pre-registration checks: Before creating the user, explicitly verify that the username and email aren’t already in use (to give users clearer error messages):
    if (ModelState.IsValid)
    {
        // 检查用户名是否已存在
        var existingUserByName = await _userManager.FindByNameAsync(model.UserName);
        if (existingUserByName != null)
        {
            ModelState.AddModelError(nameof(model.UserName), "该用户名已被使用");
            return View(model);
        }
    
        // 检查邮箱是否已存在
        var existingUserByEmail = await _userManager.FindByEmailAsync(model.Email);
        if (existingUserByEmail != null)
        {
            ModelState.AddModelError(nameof(model.Email), "该邮箱已被注册");
            return View(model);
        }
    
        // 继续创建用户...
    }
    

方案3:支持用户名或邮箱登录

Now that you’ve split the fields, let users log in with either their username or email for better usability:

  • Update the LoginViewModel: Keep the existing identifier field but rename it to something like LoginIdentifier for clarity.
  • Modify the Login action: Detect whether the input is an email or username, then authenticate accordingly:
    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            ApplicationUser user;
            // 判断输入是否是邮箱格式
            if (new EmailAddressAttribute().IsValid(model.LoginIdentifier))
            {
                user = await _userManager.FindByEmailAsync(model.LoginIdentifier);
            }
            else
            {
                user = await _userManager.FindByNameAsync(model.LoginIdentifier);
            }
    
            if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
            {
                await _signInManager.SignInAsync(user, model.RememberMe);
                return LocalRedirect(returnUrl ?? Url.Content("~/"));
            }
    
            ModelState.AddModelError(string.Empty, "无效的登录凭据");
        }
        return View(model);
    }
    

方案4:自定义Identity用户实体(进阶)

If you need more control, extend the ApplicationUser class to add additional fields or override default behavior (optional for basic separation):

public class ApplicationUser : IdentityUser
{
    // 添加自定义字段(可选)
    public string DisplayName { get; set; }
}

This lets you further customize user properties without changing core Identity logic.


内容的提问来源于stack exchange,提问作者AllocSystems

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:07:09