我使用ASP.NET Core Identity(2.0)和所有默认代码。我更改了AccountController.Login
方法以检查旧数据库,并在找不到用户时迁移用户。由于该旧数据库同时具有用户名和电子邮件,因此我在新创建的用户中填充这两个字段。
但是,如果我尝试再次使用迁移的用户登录,则使用该电子邮件不起作用,因为似乎SQL请求始终仅查找WHERE u.NormalizedUserName = @__normalizedUserName_0
。
如何使用电子邮件和用户名不同的用户启用其用户名或电子邮件的单个用户?
答案 0 :(得分:3)
感谢所有贡献者,但我认为这个问题应该得到更准确的答案。
ASP.NET Core Identity的默认模板将始终使用包含相同值的电子邮件和用户名创建用户。然后,默认登录处理程序(在AccountController.Login
或登录视图的OnPostAsync
方法中)将始终使用"电子邮件"字段作为用户名,并致电PasswordSignInAsync
。虽然代码似乎暗示它支持电子邮件,但这种方法实际上只接受用户名。为了增加整体混淆,视图正在验证您输入了有效的电子邮件,但最终将在NormalizedUserName
字段中搜索您输入的内容!
因此,如果您想要允许电子邮件,如Mark和Razvan所述,您可以使用_userManager.FindByEmailAsync
获取尝试登录的用户的实际用户名,然后使用PasswordSignInAsync
调用用户名。
作为stated by Barry Dorrans:"不,你是对的。模板最终在注册过程中使用的用户名和电子邮件相同,但无法使它们保持同步。为了解决这个丑陋的混乱局面,已经安排了2.2的工作。"。
未解决的问题here。
答案 1 :(得分:1)
您可以使用CheckPasswordAsync(user, password)
中的UserManager
方法:https://github.com/aspnet/Identity/blob/a273e349eea2be3a40b16e6947b2deab95f4b5b2/src/Core/UserManager.cs#L692
在调用该方法之前,您可以通过以下方式获取用户:
var user = await _userManager.FindByNameAsync(userName) ?? await _userManager.FindByEmailAsync(userName);
根据您当前的UserStore
实施情况,您可能需要调整FindByNameAsync
或FindByEmailAsync
或两者。
答案 2 :(得分:0)
您必须更改AccountViewModel.cs
public class LoginViewModel
{
[Required]
[Display(Name = "Логин/Email")]
//[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Пароль")]
public string Password { get; set; }
[Display(Name = "Запомнить меня")]
public bool RememberMe { get; set; }
}
AccountController.cs
public async Task Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
ApplicationUser user;
if (model.Email.Contains("@"))
user = UserManager.FindByEmail(model.Email);
else
user = UserManager.FindByName(model.Email);
var result = await SignInManager.PasswordSignInAsync(user.UserName, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Неудачная попытка входа.");
return View(model);
}
}