如何盐和比较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); 
    } 
+0

你有没有使用asp身份进行调查?所有这一切都为您的许多内置的方法照顾 –

+1

关于安全的规则1:不要自己建立:) – oerkelens

我从来没有使用过它,但基于文档...

Crypto.HashPassword加盐的并返回一个base-64编码的字符串,其中包含所有详细信息以验证密码。所以,你不需要自己添加盐。

您需要做的就是将散列结果(base64EncodedHash下面)存储在数据库中,然后将其与VerifyHashedPassword一起用于稍后进行身份验证。例如。做单元测试,像这样:

var base64EncodedHash = Crypto.HashPassword("password"); 
Assert.IsTrue(Crypto.VerifyHashedPassword(base64EncodedHash, "password")); 
Assert.IsFalse(Crypto.VerifyHashedPassword(base64EncodedHash, "otherPass")); 

https://msdn.microsoft.com/en-us/library/system.web.helpers.crypto.verifyhashedpassword(v=vs.111).aspx

要翻译给你的代码:

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地址等

而且,正如有人说...当涉及到安全...直到你是专家... ...最好使用预先存在的代码/框架来缓解你的风险。

+0

我很乐意实施暴力检查。有关如何去做的任何想法?感谢你的回答。 – Izuagbala

+0

@Izuagbala,对于蛮力检查,基本上,你所要做的只是减慢它们,这样一个好的密码将需要数百年的时间来猜测。快速谷歌应该给你很多充分的解释。但是,简而言之:1)制作数据库表或缓存IpLogAttempts {Ip,AttemptsCount,LastAttempt}。 2)当IP尝试登录时,如果超过最大失败/时间,则阻止它。 3)如果它尚未被阻止,请检查密码,如果登录错误,请增加您的AttemptsCount。即使阻止IP 5-20分钟,也会大大降低暴力攻击成功的几率。 –

+0

@Izuagbala,这是一个更彻底的解释,我扔在一起,因为评论是没有足够的空间来解释这一切:http://coding.xingcr.com/securing-website-against-brute-force-attacks/ –