【问题标题】:How to validate Password from database when password is hashed对密码进行哈希处理时如何从数据库中验证密码
【发布时间】:2021-12-12 01:19:20
【问题描述】:

您好,我有一个程序,我通过 WPF 向用户请求用户名和密码,然后我将数据发送到存储数据的数据库。

 private void btnRegister_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                using (SqlConnection connection = new SqlConnection(ConnectionSQL.conn))
                {
                    SqlCommand command = new SqlCommand("INSERT INTO USERTABLE " +
                                                        "VALUES(@Username, @Password);" +
                                                        "Select SCOPE_IDENTITY();", connection);
                    command.Parameters.AddWithValue("@Username", txtbUsername.Text);
                    command.Parameters.AddWithValue("@Password", Utils.hashPassword(txtbPassword.Text));
                    connection.Open();

                    SqlDataAdapter adapter = new SqlDataAdapter();
                    adapter.InsertCommand = command;

                    int id = Convert.ToInt32(adapter.InsertCommand.ExecuteScalar());
                    MessageBox.Show("User Registered! User has been added to the database: " + id);
                    adapter.Dispose();

                    String Username = txtbUsername.Text;
                    String Password = txtbPassword.Text;
                    Users temp = new Users(id, Username, Password);

                    Login L = new Login();
                    arrUsers.Add(temp);
                    Hide();
                    L.ShowDialog();
                    
                }
            }
            catch (SqlException ex)
            {
                MessageBox.Show("Error Connecting to the Database", "Connection Error" + ex.ToString());
            }

        }

我创建了一个函数来将密码作为哈希值存储在数据库中。

 public class Utils
    {
        public static string hashPassword(String password)
        {
            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();

            byte[] password_bytes = Encoding.ASCII.GetBytes(password);
            byte[] encrypted_bytes = sha1.ComputeHash(password_bytes);
            return Convert.ToBase64String(encrypted_bytes);


        }
    }

当我尝试登录并验证密码存储为哈希时,它不起作用。

 private void btnLogin_Click(object sender, RoutedEventArgs e)
       {
           try
           { 
               using (SqlConnection connection = new SqlConnection(ConnectionSQL.conn))
               {
                   connection.Open();
                   String Username = Convert.ToString(txtbUsername.Text);
                   String Password = Convert.ToString(txtbPassword.Text);

                   String sql = "SELECT * FROM USERTABLE where Username = '" + Username + "' " +
                       "AND Password = '" + Password + "' ;";
                   SqlCommand command = new SqlCommand(sql, connection);
                   SqlDataReader reader = command.ExecuteReader();
                   if (reader.HasRows)
                   {
                       MessageBox.Show("You Have Successfully Logged In");
                       MainWindow Main = new MainWindow();
                       txtbUsername.Text = "";
                       txtbPassword.Text = "";
                       this.Hide();
                       Main.ShowDialog();
                       this.Show();
                   }
                   else
                   {
                       MessageBox.Show("Invalid Credentials");
                   }
                   reader.Close();
                   command.Dispose();
               }
           }
           catch (SqlException ex)
           {
               Console.WriteLine(ex.ToString());
           }
           Console.ReadLine();
       }

虽然当我不在数据库中散列密码时它可以工作。有什么解决办法吗?

【问题讨论】:

  • 请注意,存储密码是一个难题,您几乎应该始终依赖于为您完成所有这些工作的现有框架。例如,这里你没有给你的哈希加盐。
  • @SebastianMarshall:乍一看,您似乎只是忘记在比较之前对密码进行哈希处理......?
  • 您没有在登录时散列密码。而且您还应该使用参数化查询进行登录(就像您在创建用户时所做的那样)
  • 你真的应该考虑一下 DavidG 所说的。试试看这个:stackoverflow.com/questions/2005054/…
  • 您编写了一个客户端应用程序,客户端直接访问您的数据库。你已经输了。任何人都可以从代码库中提取数据库凭据或嗅探网络流量,并对您的数据库做任何他们想做的事情。他们可以擦除所有内容、阅读其他人的信息、插入他们自己的特权帐户,或者他们想要的任何其他内容。您需要在客户端应用程序和数据库之间有一个 API。相比之下,所有其他关于加盐或参数化查询的问题都相形见绌。

标签: c# sql


【解决方案1】:

您不会将非散列密码与散列密码进行比较。从客户端获取密码时,您需要再次对该密码进行哈希处理,然后匹配哈希值。如果它们匹配,它应该返回成功。

更新这个应该可以解决它:

String Password = Convert.ToString(Utils.hashPassword(txtbPassword.Text));

但这里还有更多明显的问题需要您解决:

首先:您需要使用SqlParameter 将值添加到您的WHERE 子句,而不是直接将值添加到您的SQL 命令中。这是为了避免 SQL 注入。

其次:将数据访问层从应用程序中分离出来。如果访问您的数据库的代码可供客户端使用,这将是一个很大的风险。

还有一些其他的事情我会改变。但这些应该是很好的起点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 2019-04-21
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    相关资源
    最近更新 更多