我正在做一个 ASP.NET Core 6.0 项目。我添加了身份库,它添加了 Razor 页面。
只要用户名和电子邮件相同,注册和登录就可以正常工作。但是,我希望将用户名作为纯字符串,将电子邮件作为典型的电子邮件,用户可以使用用户名或电子邮件登录。
我已经定制了注册页面,我在其中收集了用户名和电子邮件。我没有看到任何可以实现的示例代码。我看到一些示例代码不从用户那里收集用户名。而在代码中,用户名被保存为电子邮件。本质上,这两个值将是相同的。
如果你想使用用户名作为纯字符串,电子邮件作为典型的电子邮件,那么你需要输入一个
UserName
属性并在注册时将其用作数据库的UserName
字段,因为Identity会存储 Email
默认为 UserName
字段。
在
Regirster.cshtml.cs
中,需要在InputModel
中添加一个属性,并在OnPostAsync
方法中将其存储到数据库中:
public class InputModel
{
//other properties
[Required]
[Display(Name = "UserName")]
public string UserName { get; set; }
}
然后,改变
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
到
await _userStore.SetUserNameAsync(user, Input.UserName, CancellationToken.None);
在
OnPostAsync
方法中。
在
Register.cshtml
中,添加输入用户名的输入:
<div class="form-floating">
<input asp-for="Input.UserName" class="form-control" autocomplete="username" aria-required="true" />
<label asp-for="Input.UserName"></label>
<span asp-validation-for="Input.UserName" class="text-danger"></span>
</div>
如果您想使用
Username
或Email
登录,则需要对InputModel
中的OnPostAsync
和Login.cshtml.cs
方法进行一些调整。
默认的InputModel:
public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
删除
EmailAddress
注释并定义Email
的显示文本:
[Required]
[Display(Name = "Username/Email")]
public string Email { get; set; }
然后改变
OnPostAsync
方法如下:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (Input.Email.IndexOf('@') > -1)
{
//Validate email format
string emailRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
@"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
@".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
Regex re = new Regex(emailRegex);
if (!re.IsMatch(Input.Email))
{
ModelState.AddModelError("Email", "Email is not valid");
}
}
else
{
//validate Username format
string userNameRegex = @"^[a-zA-Z0-9]*$";
Regex re = new Regex(userNameRegex);
if (!re.IsMatch(Input.Email))
{
ModelState.AddModelError("Email", "Username is not valid");
}
}
if (ModelState.IsValid)
{
var userName = Input.Email;
if (userName.IndexOf('@') > -1)
{
var user = await _userManager.FindByEmailAsync(Input.Email);
if (user == null)
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
else
{
userName = user.UserName;
}
}
var result = await _signInManager.PasswordSignInAsync(userName, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
编辑:
如果出现如下错误:
The name '_userManager' does not exist in the current context
,那是因为你没有将UserManager
注入到LoginModel
中:
public class LoginModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<LoginModel> _logger;
public LoginModel(SignInManager<IdentityUser> signInManager, ILogger<LoginModel> logger, UserManager<IdentityUser> userManager)
{
_signInManager = signInManager;
_logger = logger;
_userManager = userManager;
}
//...
}