提问者:小点点

在这段代码中如何防止SQL注入?


我怎样才能防止这些获得SQL注入的代码呢? 这是我正在学习的登录系统。 这是密码!

            if (!(string.IsNullOrWhiteSpace(textBox1.Text)) && !(string.IsNullOrWhiteSpace(textBox2.Text)))
        {

            MySqlConnection mcon = new MySqlConnection("datasource = 127.0.0.1; port = 3306; username = root; password = ; database = rpgmaster;");

            mcon.Open();

            DataTable table = new DataTable();

            MySqlDataAdapter adapter = new MySqlDataAdapter("Select * From users where Username = '" + textBox2.Text + "' and password = '" + textBox1.Text + "'", mcon);
           
            adapter.Fill(table);

            if (table.Rows.Count <= 0)
            {
                MessageBox.Show("Você não está registrado!");
            }
            else
            {
                MessageBox.Show("Logado com sucesso! ");
            }

            mcon.Close();
        }

谢谢你的帮助! 真的很感激!


共3个答案

匿名用户

请尝试使用参数,请参阅下面更新的代码示例:

 if (!(string.IsNullOrWhiteSpace(textBox1.Text)) && !(string.IsNullOrWhiteSpace(textBox2.Text)))
        {

            using (MySqlConnection mcon = new MySqlConnection("datasource = 127.0.0.1; port = 3306; username = root; password = ; database = rpgmaster;"))
            {
                mcon.Open();

                MySqlCommand cmd = new MySqlCommand("Select * from users where username=?username and password=?password", mcon);
                cmd.Parameters.Add(new MySqlParameter("username", textBox2.Text));
                cmd.Parameters.Add(new MySqlParameter("password", textBox1.Text));

                MySqlDataReader dr = cmd.ExecuteReader();
                if (dr.HasRows == true)
                {
                    MessageBox.Show("Você não está registrado!");
                }
                else
                {
                    MessageBox.Show("Logado com sucesso! ");
                }

            }

        }

匿名用户

如果您正在学习,您也许可以从这种旧的低级的数据访问方式转向使用一些更现代,更简单的方式。 Dapper就是一个库的例子,它并不比你已经知道的东西有很大的飞跃,但却能让你的生活更美好:

using(var conn = new MySqlConnection("conn str here"){

  var sql = "SELECT count(*) FROM tblUsers WHERE username = @u AND password = @p";
  var prm = new { 
    u = txtUsername.Text,               //give your textboxes better names than textbox2,textbox1!
    p = txtPassword.Text.GetHashCode() //do NOT store plain text passwords!
  };
  bool valid = await conn.QuerySingleAsync<int>(sql, prm) > 0;

  if(valid)
    ... valid login code
  else
    ... invalid login
}

关于这一点的一些注意事项:

  • Dapper是一种设备,您只需将sql和参数值提供给
  • sql保存@parameters名称,如@u
  • 匿名类型化对象具有与参数名称同名的属性,具有一个值,如u=“My UserName”
  • 运行查询时使用async/await; 衣冠楚楚让这件事变得容易。 避免在运行需要10秒的查询时干扰UI
  • 在这种情况下,您只需要让db对匹配记录进行计数,不需要下载所有记录来查找是否有匹配记录,因此我们使用QuerySingleAsync查询类型为it的单个值,如果该值大于0,则登录有效
  • 永远不要将密码以明文形式存储在数据库中。 使用单向散列函数,如MD5,SHA256等,甚至是低字符串。GetHashCode比存储明文更好,特别是因为人们一直使用相同的密码,所以任何人闯入你的数据库(非常容易,密码就在代码中)都会泄露密码对待人们可能在他们的银行中使用的密码。我们不能真的问,一方面,如何防止一个巨大的安全漏洞,如SQL注入,然后另一方面,留下一个巨大的安全漏洞,如明文密码;)
  • 总是为文本框命名一个比真正默认的textboxX更好的名称--这需要几秒钟的时间,并且使代码易于理解。 如果Microsoft在整个框架中调用它们的所有类属性名,例如String2,Int27,那么它将完全不可用
  • 生命太短暂,不能把它花在编写AddWithValue语句上; 使用Dapper,实体框架,强类型数据集..

Dapper让事情变得更好的地方是它能够将对象转换为查询,反之亦然; 这只是一个基本的计数示例,但假设您有一个user类:

class User
{
  string Name { get; set; }
  string HashedPassword { get; set; }
  int age {get; set; }
}

并且您有一个类似的表tblUsers(列名与属性名类似),那么您可以进行如下查询:

User u = new User() { Name = "someuser" };
User t = await conn.QuerySingleAsync<User>("SELECT Name, HashedPassword, Age FROM tblUsers WHERE Name = @Name", u);

我们想从某个用户那里查找所有的信息,所以我们用这个名称集创建一个新用户(我们也可以使用匿名类型),而不使用其他任何东西,并将其作为参数参数传递。 Dapper将看到包含@Name的查询,从我们传入的用户u中提取名称的内容,并运行查询,从响应中提取所有数据,为我们创建一个新用户,并填充其所有属性。 要用这种老方法,我们必须:

  • 有命令,
  • 有连接,
  • 具有参数化命令,
  • 添加参数,
  • 打开连接,
  • 运行sql,
  • 获取阅读器,
  • 检查读取器是否有行,
  • 在读取器上循环读取第一行,
  • 创建新用户,
  • 使用reader.getInt/string等将列值逐个拉出,
  • 最后返回新用户
  • 哦,处理掉所有db的东西

写那些代码是重复的,而且真的很枯燥。 在计算中,当我们有一些重复和枯燥的事情,我们一生中需要做成千上万次(比如序列化到json,调用webservice,设计windows UI)时,我们会找到一些方法让计算机去做那些重复和枯燥的事情; 他们比我们做得更快更准确。 这正是Dapper所做的; 它消除了这种枯燥的重复,并将其简化为一行,在一行中您可以说出您想要返回的内容,使用什么查询,使用什么参数。 并且它保持您的UI工作:

await x.QueryAsync<type>(query, parameters)

赢了。 寻找一些时髦的教程!

匿名用户

使用参数

using (MySqlConnection mcon = new MySqlConnection(connectionString))
{
        string commandText = "SELECT * FROM users WHERE Username = '@tbxText'"
        SqlCommand command = new SqlCommand(commandText, mcon);
        
        command.Parameters.AddWithValue("@tbxText", textBox2.Text);

}