允许用户使用Email或UserName(AspNet.Identity)登录

aar*_*len 7 c# authentication asp.net-mvc asp.net-identity

我想知道是否有更有效的路线可以在这里.使用AspNet.Identity我想允许用户使用他们的UserName或登录到同一文本框Email.我继续前进并解决了这个问题AccountController Login ActionResult.我在打电话之前运行检查:

var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: true);
Run Code Online (Sandbox Code Playgroud)

支票:

//TODO: determine if there is a more efficient way to allow user to login either with Email || UserName
if (model.UserName.Contains("@"))
{
    using (var context = new ApplicationDbContext())
    {
        model.UserName = (context.Users.Any(p => p.Email == model.UserName)) ?
          context.Users.SingleOrDefault(p => p.Email == model.UserName).UserName :
          model.UserName;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里的担忧有两个方面:

  1. 他们是一种更有效的实践方法.
  2. 我是否通过这种方式引入任何新的安全风险或性能风险?

我将整个ActionResult以下内容作为参考.

//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    //TODO: determine if there is a more efficient way to allow user to login either with Email || UserName
    if (model.UserName.Contains("@"))
    {
        using (var context = new ApplicationDbContext())
        {
            model.UserName = (context.Users.Any(p => p.Email == model.UserName)) ?
              context.Users.SingleOrDefault(p => p.Email == model.UserName).UserName :
              model.UserName;
        }
    }

    // This doesn't count login failures towards account lockout
    // To enable password failures to trigger account lockout, change to shouldLockout: true
    var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: true);
    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("", "Invalid login attempt.");
            return View(model);
    }
}
Run Code Online (Sandbox Code Playgroud)

相关的github问题#2#4

Mar*_*Ban 11

会有一个安全问题.如果您知道他的电子邮件,您可以获得其他用户的用户名:

  1. 写他的电子邮件和错误的密码
  2. 然后系统加载相应的用户名,执行失败的密码验证并返回带有覆盖用户名的模型

我会声明新变量而不是model.UserName重用.如果您使用FirstOrDefault,您的查询会更有效:

    var userName = model.UserName;
    using (var context = new ApplicationDbContext())
    {
       var user = context.Users.FirstOrDefault(p => p.Email == model.UserName);
       if (user != null)
       {
           userName = user.UserName;
       }
    }

var result = await SignInManager.PasswordSignInAsync(userName, model.Password, model.RememberMe, shouldLockout: true);
Run Code Online (Sandbox Code Playgroud)