【问题标题】:Hashed password is not recognized after changing it更改后无法识别散列密码
【发布时间】:2015-10-01 09:39:51
【问题描述】:

我的密码就在registration.aspx 中。在我的业务层中有此代码:

public static string CreateSHAHash(string Phrase)
    {
        SHA512Managed HashTool = new SHA512Managed();
        Byte[] PhraseAsByte = System.Text.Encoding.UTF8.GetBytes(string.Concat(Phrase));
        Byte[] EncryptedBytes = HashTool.ComputeHash(PhraseAsByte);
        HashTool.Clear();
        return Convert.ToBase64String(EncryptedBytes);
    }

以及注册页面中的这段代码:

scm.Parameters.AddWithValue("@Password", BusinessLayer.ShoppingCart.CreateSHAHash(txtPW.Text));

有了上面的代码,密码在数据库中被散列,当我用这个代码登录时它工作正常:

protected void btn_Login_Click(object sender, EventArgs e)
    {
        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString);
        conn.Open();
        string checkuser = "select count(*) from UserData where Username = '" + txtUser.Text + "'";
        SqlCommand scm = new SqlCommand(checkuser, conn);
        int temp = Convert.ToInt32(scm.ExecuteScalar().ToString());
        conn.Close();
        if (temp == 1)
        {
            conn.Open();
            string checkPassword = "select Password from UserData where Username ='" + txtUser.Text + "'";
            SqlCommand passCom = new SqlCommand(checkPassword, conn);
            string password = passCom.ExecuteScalar().ToString();
            if (password == BusinessLayer.ShoppingCart.CreateSHAHash(txtPassword.Text))
            {
                Session["New"] = txtUser.Text;
                Response.Write("<script>alert('Logged In')</script>");
                Response.Redirect("OrderNow.aspx");
            }
            else
            {
                lblcrederror.Text = ("Credentials dont match");
            }

        }
        else
        {
            lblcrederror.Text = ("Credentials dont match");
        }

但是,当我在 changepassword.aspx 中使用此代码更改它时,它不会让我使用新密码。

protected void btn_update_Click(object sender, EventArgs e)
    {
        SqlConnection con = new SqlConnection(conn);
        con.Open();
        str = "select * from UserData ";
        com = new SqlCommand(str, con);
        SqlDataReader reader = com.ExecuteReader();
        while (reader.Read())
        {
            if (BusinessLayer.ShoppingCart.CreateSHAHash(txt_cpassword.Text) == reader["Password"].ToString())
            {
                up = 1;
            }
        }
        reader.Close();
        con.Close();
        if (up == 1)
        {
            con.Open();
            str = "update UserData set Password=@Password where UserName='" + Session["New"].ToString() + "'";
            com = new SqlCommand(str, con);
            com.Parameters.Add(new SqlParameter("@Password", SqlDbType.VarChar, 50));
            com.Parameters["@Password"].Value = BusinessLayer.ShoppingCart.CreateSHAHash(txt_npassword.Text);
            com.ExecuteNonQuery();
            con.Close();
            lbl_msg.Text = "Password changed Successfully";
        }
        else
        {
            lbl_msg.Text = "Please enter correct Current password";
        }
    }

我在这里缺少什么?

【问题讨论】:

  • 它是否在数据库中得到更新?更改密码哈希后是否更短?也许 50 正在截断哈希?
  • 好主意!让我检查
  • 你是个传奇。有什么办法可以弥补你吗? @BjørnØyvindHalvorsen
  • 还可以考虑保留密码历史的设计,即不更新现有密码而是插入新密码记录。然后,创建第一个密码与创建后续密码完全相同 - 都使用相同的插入命令。密码历史可以防止用户总是使用相同的密码。
  • 嘿好主意@Polyfun。你有任何关于我如何做到这一点的参考或样本吗?谢谢! :)

标签: c# hash login passwords


【解决方案1】:

检查 50 是否截断散列。

com.Parameters.Add(new SqlParameter("@Password", SqlDbType.VarChar, 50));

在旁注中,我看到您的解决方案对 SQL 注入非常开放。

 "select Password from UserData where Username ='" + txtUser.Text + "'";

用户可以在文本框中编写 sql 语句,并劫持您的数据库、创建自己的表或删除整个数据库。您应该始终参数化查询。我看到您对 Update 语句执行了此操作,但您应该考虑对所有变量执行此操作。

这会很快创建大量代码,因此我还会考虑制作一个 SQL 包装器,它可以包装您重复的所有内容。完成重构后,它可能看起来像这样:

var sql = new SqlWrapper("select Password from UserData where Username = @username", txtUser.Text);
var dataSet = sql.Execute();

然后您可以将所有连接字符串、命令++隐藏在此包装器后面,只告诉包装器您真正关心的内容。

您还应该考虑使用盐作为密码。如果您和我的密码相同,则哈希值将相同。盐可以解决这个问题。

一篇关于密码安全的好文章 -> https://crackstation.net/hashing-security.htm

【讨论】:

  • 不相信需要 SqlWrapper。我发现这只会使其他人更难以理解代码,因为他们必须遍历您的(写得不好?)包装器代码才能获得他们已经拥有的东西(.Net 库)。 SqlParameters可以在一行中创建和添加。
  • 它被称为外观模式。制作复杂、简单的东西。作为一名开发人员,我每天都会阅读大量代码。我必须通读的代码行越少越好。编写好的外观,这是有道理的,并且足够动态以供您使用。这是一个很好的做法,并受到鼓励 -> en.wikipedia.org/wiki/Facade_pattern SqlParameters、SqlConnection 和 SqlCommand 被抽象掉了......一件好事......
  • 我明白这一点,但根据我的经验,普通程序员不太擅长编写外观,而且我认为没有必要像 System.Data.SqlClient 那样理解,因为它已经一个立面。无论如何,为您自己的图书馆创建一个外观。
  • 如果与你共事的普通程序员不擅长编写外观,那么他们不应该是建筑师。如果您知道如何编写好的外观,那么您绝对应该制作它们,这样您的不太好的开发人员就不必摆弄他们一无所知的东西。 System.Data.SqlClient 可以做很多事情。哪个好。但很少需要。如果这些开发人员不好,那么你应该帮助他们在处理大型库时少犯错误,通过让他们成为一个门面,或者更好地教他们成为更好的开发人员:) 内部研讨会和点对点 :)
猜你喜欢
  • 1970-01-01
  • 2023-02-09
  • 2019-06-18
  • 2015-12-20
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 2019-07-17
  • 1970-01-01
相关资源
最近更新 更多