Speak now
Please Wait Image Converting Into Text...
Embark on a journey of knowledge! Take the quiz and earn valuable credits.
Challenge yourself and boost your learning! Start the quiz now to earn credits.
Unlock your potential! Begin the quiz, answer questions, and accumulate credits along the way.
General Tech Learning Aids/Tools 2 years ago
Posted on 16 Aug 2022, this text provides information on Learning Aids/Tools related to General Tech. Please note that while accuracy is prioritized, the data presented might not be entirely correct or up-to-date. This information is offered for general knowledge and informational purposes only, and should not be considered as a substitute for professional advice.
Turn Your Knowledge into Earnings.
I'm writing a theoretical MVC application to aid in learning more about ASP Identity 2. In real terms I'm new to ASP Identity as a whole but thought I'd jump in in this release as
it's the default in new projects and
everything I read about it seems to mostly suit my needs.
There is one issue that I need to be able to overcome. That issue is locking out users. I want to allow administrators the facility to be able to lock out a user should they wish to restrict their access.
From what I've read so far, there is a temporary lockout solution for example when the user tries their password incorrectly x number of times for y number of minutes. This doesn't seem to be the recommended method for more long term solutions.
For a longer term solution, I've added a Locked property to the ApplicationUser class in Entity Framework code first:
Locked
public class ApplicationUser : IdentityUser { public string FirstName { get; set; } public string Surname { get; set; } public bool Locked { get; set; } [NotMapped] public string FullName { get { return FirstName + " " + Surname; } } }
Getting to the point of my question though, which is, is my modified ActionResult Login method secure and efficient? I don't want to make unnecessary roundtrips to the database and I also don't want to unwillingly do anything unsecure.
ActionResult Login
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { if (!ModelState.IsValid) { return View(model); } // MY LOCKED CHECK CODE: // Check if the user is locked out first // 1. Fail if it is // 2. If user isn't found then return invalid login atempt // 3. If the user is found and it isn't locked out then proceed with the login as usual var user = UserManager.Users.Where(u => u.UserName == model.Email).SingleOrDefault(); if (user != null) { if (user.Locked) { return View("Lockout"); } } else { ModelState.AddModelError("", "Invalid login attempt."); return View(model); } // END MY CODE // 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.Email, 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 REPLY 0 views 0 likes 0 shares Facebook Twitter Linked In WhatsApp
Only focusing on this part
var user = UserManager.Users.Where(u => u.UserName == model.Email).SingleOrDefault(); if (user != null) { if (user.Locked) { return View("Lockout"); } } else { ModelState.AddModelError("", "Invalid login attempt."); return View(model); }
Are you aware that if the Users contains more than one user with the same Email the call to SingleOrDefault will throw an InvalidOperationException ? If you are 100 percent sure that this won't ever happen then there won't be a problem.
Users
Email
SingleOrDefault
InvalidOperationException
In its current state this linq query will for each user query the model for the Email property. If you store it in a variable the access will be much faster.
model
Checking first if the user == null will make it more obvious what is happening. As I first looked over this code I thought hey, how should the code after the if..else ever be reached.
user == null
if..else
Applying this will lead to
string email = model.Email; var user = UserManager.Users.Where(u => u.UserName == email).SingleOrDefault(); if (user == null) { ModelState.AddModelError("", "Invalid login attempt."); return View(model); } if (user.Locked) { return View("Lockout"); }
This looks far better IMO and is more readable.
Usually a username isn't checked in a case sensitive way so instead of u.UserName == email you should use the string.equals() method.
u.UserName == email
string.equals()
This method takes as the third parameter a StringComparison enum which defines how the comparison will take place. The best one for all cultures, for instance using a turkish locale can make problems (does-your-code-pass-turkey-test), will be to use StringComparison.OrdinalIgnoreCase.
StringComparison
StringComparison.OrdinalIgnoreCase
string email = model.Email; var user = UserManager.Users.Where(u => string.Equals(u.UserName, email, StringComparison.OrdinalIgnoreCase)).SingleOrDefault(); if (user == null) { ModelState.AddModelError("", "Invalid login attempt."); return View(model); } if (user.Locked) { return View("Lockout"); }
No matter what stage you're at in your education or career, TuteeHub will help you reach the next level that you're aiming for. Simply,Choose a subject/topic and get started in self-paced practice sessions to improve your knowledge and scores.
General Tech 10 Answers
General Tech 7 Answers
General Tech 3 Answers
General Tech 9 Answers
General Tech 2 Answers
Ready to take your education and career to the next level? Register today and join our growing community of learners and professionals.