如何盐和比较ASP.NET MVC中的密码
我正在写一个ASP.NET程序,我需要将用户密码存储在数据库中。但是当我将数据库中的密码与用户输入密码进行比较时,我得到的密码不匹配。即使用户密码正确。如何盐和比较ASP.NET MVC中的密码
中的密码哈希:
string PasswordSalt = Crypto.HashPassword(DateTime.Now.ToString());
string hashPassword = Crypto.HashPassword(formcollection["PassWord"]); //Hash User PassWord
user.PassWord = Crypto.HashPassword(PasswordSalt + hashPassword);//Add Salt to Password For Futher Security
user.PassWordSalt = PasswordSalt;
密码验证:
Users ThisUser = Users.UsersGetByEmail((string)Session["email"]);
string checkpassword = ThisUser.PassWord;
//User Inputed password.
string password = user.PassWord;
if (password != null)
{
//Need to fix.
string encrypt_password = Crypto.HashPassword(password);
string salted_password = Crypto.HashPassword(ThisUser.PassWordSalt + encrypt_password);
//bool does_password_match = Crypto.VerifyHashedPassword(checkpassword, password);
if (checkpassword == salted_password)
{
//Check if the inputed password matches the password from the Database.
//Remember to give session based on the user_id.
Session["user_id"] = ThisUser.Id;
return RedirectToAction("Promise");
}
else
{
ModelState.AddModelError("PassWord", "Wrong Password, Please Enter Correct Password");
return View(user);
}
我从来没有使用过它,但基于文档...
Crypto.HashPassword加盐的并返回一个base-64编码的字符串,其中包含所有详细信息以验证密码。所以,你不需要自己添加盐。
您需要做的就是将散列结果(base64EncodedHash
下面)存储在数据库中,然后将其与VerifyHashedPassword一起用于稍后进行身份验证。例如。做单元测试,像这样:
var base64EncodedHash = Crypto.HashPassword("password");
Assert.IsTrue(Crypto.VerifyHashedPassword(base64EncodedHash, "password"));
Assert.IsFalse(Crypto.VerifyHashedPassword(base64EncodedHash, "otherPass"));
要翻译给你的代码:
user.PassWord = Crypto.HashPassword(formcollection["PassWord"]);
然后验证(添加怪癖评论我看到):
//Why are you storing "email" in Session before user is validated??? Seems off.
Users ThisUser = Users.UsersGetByEmail((string)Session["email"]);
string userInputPassword = user.PassWord; //this should be coming from POST
if(ThisUser != null && Crypto.VerifyHashedPassword(ThisUser.PassWord, userInputPassword)) {
Session["user_id"] = ThisUser.Id;
return RedirectToAction("Promise");
}
else {
ModelState.AddModelError("PassWord","Your username or password are incorrect");
return View(user);
}
理想情况下,正如我通过改变错误文字所指出的那样......您还想给用户同样的错误消息是否用户名/电子邮件或密码错误。如果电子邮件没有返回帐户,那么您的代码可能会返回一个不同的错误,但您不想向暴力攻击者提供那么多信息。
您还需要投入一些强力检查,这样如果他们失败的尝试次数太多,阻塞的时间。X量IP地址等
而且,正如有人说...当涉及到安全...直到你是专家... ...最好使用预先存在的代码/框架来缓解你的风险。
我很乐意实施暴力检查。有关如何去做的任何想法?感谢你的回答。 – Izuagbala
@Izuagbala,对于蛮力检查,基本上,你所要做的只是减慢它们,这样一个好的密码将需要数百年的时间来猜测。快速谷歌应该给你很多充分的解释。但是,简而言之:1)制作数据库表或缓存IpLogAttempts {Ip,AttemptsCount,LastAttempt}。 2)当IP尝试登录时,如果超过最大失败/时间,则阻止它。 3)如果它尚未被阻止,请检查密码,如果登录错误,请增加您的AttemptsCount。即使阻止IP 5-20分钟,也会大大降低暴力攻击成功的几率。 –
@Izuagbala,这是一个更彻底的解释,我扔在一起,因为评论是没有足够的空间来解释这一切:http://coding.xingcr.com/securing-website-against-brute-force-attacks/ –
你有没有使用asp身份进行调查?所有这一切都为您的许多内置的方法照顾 –
关于安全的规则1:不要自己建立:) – oerkelens