2014-09-24 167 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

相關問題