2014-09-24 135 views
5

我想知道是否有一个更有效的路线来采取。使用AspNet.Identity我希望允许用户使用他们的UserNameEmail登录到同一个文本框。我继续在AccountController Login ActionResult中解决这个问题。我打电话之前运行检查:允许用户使用电子邮件或用户名(AspNet.Identity)登录

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. 我是否以这种方式引入了新的安全风险或性能风险?

我包括下面的整个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

+2

您可以先不检查条目是否具有“@”。 – 2014-09-24 05:35:36

+0

@RedSerpent我检查该条目是否具有“@”的原因是因为如果我不需要,我不想用'context.Users.Any' LINQ查询命中数据库。碰到数据库会是一个更好的解决方案吗?你有什么问题来检查'@'? – aaronmallen 2014-09-24 05:39:50

+0

当我以Identity 1.0开头时,我遇到了同样的问题,我不得不同时插入email和userName字段。 – DSR 2014-09-24 08:27:35

回答

8

将会有一个安全问题。你可以得到其他用户的用户名,如果你知道他的电子邮件:

  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); 
+0

所有有效的点,我一定会介绍一些这些变化。但是,这仍然使用我已经使用的基本相同的方法,是不是有一种方法,这通常是通过'AspNet.Identity'完成的? – aaronmallen 2014-09-24 17:47:41

+1

@aaronmallen我不知道,但我认为你的解决方案是足够好的。 – 2014-09-24 17:59:10

相关问题