【问题标题】:How to salt and compare password in ASP.NET MVC如何在 ASP.NET MVC 中加盐和比较密码
【发布时间】:2018-01-25 03:53:42
【问题描述】:

我正在编写一个 ASP.NET 程序,我需要将用户密码存储在数据库中。但是当我将数据库中的密码与用户输入的密码进行比较时,密码不匹配。即使用户密码正确。

密码哈希:

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);
    }

【问题讨论】:

  • 您是否考虑过使用 asp 身份?所有这些都由许多内置方法为您处理
  • 关于安全性的规则 1:不要自己构建 :)

标签: c# asp.net-mvc authentication cryptography passwords


【解决方案1】:

我没用过,但是根据文档...

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"]);

然后进行验证(为我看到的怪癖添加了 cmets):

//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);
}

理想情况下,正如我对错误文本的更改所表明的那样……无论用户名/电子邮件或密码是否错误,您还希望向用户提供相同的错误消息。如果电子邮件没有返回帐户,您的代码可能会返回不同的错误,但您不想向暴力攻击者提供那么多信息。

您还需要进行一些蛮力检查,以便如果他们尝试失败的次数过多,则将该 IP 地址阻止 X 时间。等等。

而且,正如有人所说...在安全方面...直到您成为 专家...最好使用预先存在的代码/框架来减轻您的负担 风险。

【讨论】:

  • 我很乐意实施暴力检查。关于如何去做的任何想法?感谢您的回答。
  • @Izuagbala,对于蛮力检查,基本上,您要做的就是减慢它们的速度,以便一个好的密码需要数百年才能猜出。一个快速的谷歌应该会给你很多完整的解释。但是,简而言之:1)制作数据库表或缓存 IpLogAttempts { Ip, AttemptsCount, LastAttempt }。 2)当IP尝试登录时,如果超过最大失败/时间,则阻止它。 3) 如果尚未被阻止,请检查密码,如果登录错误,请增加您的 AttemptsCount。即使阻止一个 IP 5-20 分钟,也会大大降低暴力攻击成功的机会。
  • @Izuagbala,这里有一个更彻底的解释,因为 cmets 没有足够的空间来解释这一切:coding.xingcr.com/securing-website-against-brute-force-attacks
  • 感谢@Kelvin 花时间研究这个话题。我很感激。
猜你喜欢
  • 2013-02-13
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
  • 2016-04-09
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 2020-07-09
相关资源
最近更新 更多