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

时间:2014-09-24 05:28:51

标签: c# asp.net-mvc authentication asp.net-identity

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

var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: true);

检查:

//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;
    }
}

我的担忧有两个方面:

  1. 这是一种更有效的实用方法。
  2. 我是否通过这种方式介绍任何新的安全风险或性能风险?
  3.   

    我将以下整个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);
        }
    }
    
      

    相关的github问题#2#4

1 个答案:

答案 0 :(得分:11)

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

  1. 写下他的电子邮件和错误的密码
  2. 然后系统加载相应的用户名,执行失败的密码验证并返回带有覆盖用户名的模型
  3. 我会声明新变量而不是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);