2

我正在尝试防止 sql 注入:例如 1=1 等。第一次这样做,我不确定我是否做得对?

这是代码:连接字符串在那里我只是为了这个问题而删除了它。

   public void btnSubmit_Click(object sender, EventArgs e)
    {

        String login = txtUser.Text;
        String pass = txtPass.Text;

            string connString = "";
            SqlConnection conn = new SqlConnection(connString);
            conn.Open();



            SqlCommand cmd = new SqlCommand("Select Users,Pass from logintable where Users='" + txtUser.Text + "' and Pass='" + txtPass.Text + "'", conn);

            cmd.Parameters.Add("@Users", SqlDbType.VarChar, 20).Value = login;


            SqlDataReader dr=cmd.ExecuteReader();
            if(dr.Read())
            {
                new Login().Show();
            }
            else
            {
                 lblFail.Text="Invalid username or password";
           }





        }
4

5 回答 5

2

您直接将值传递给您的查询。它会导致 Sql 注入。所以你需要使用 Sql 参数来避免它。这是给你的一个想法

SqlCommand cmd = new SqlCommand("Select Users,Pass from logintable where Users=@user and Pass=@password", conn);
cmd.Parameters.AddWithValue("@user", txtUserName.Text);
cmd.Parameters.AddWithValue("@password", txtPassword.Text);
reader = cmd.ExecuteReader();
于 2013-04-17T00:11:01.770 回答
1

请注意您在以下位置使用字符串连接:

"Select Users,Pass from logintable where Users='" + txtUser.Text + "' and Pass='" + txtPass.Text + "'"

这就是使您的代码容易受到注入的原因。您需要参数占位符:

"Select Users, Pass from logintable where Users=@Users and Pass=@Pass", conn);

您可以在此处找到有关如何正确使用参数的完整示例。

于 2013-04-17T00:10:02.800 回答
0

不,这是完全错误的。您仍然可以通过txtUser.Textand注入txtPass.Text,因为您使用的是字符串连接。

您需要在查询中为这两个值使用参数,然后.Text在执行前将这两个属性绑定到查询上。

        SqlCommand cmd = new SqlCommand("Select Users,Pass from logintable where Users=@username and Pass=@password", conn);
        cmd.Parameters.AddWithValue("@username", txtUser.Text);
        cmd.Parameters.AddWithValue("@password", txtPass.Text);

当然,您永远不应该像这样直接以明文形式存储密码。您应该研究正确的密码存储做法!

于 2013-04-17T00:10:47.750 回答
0

您正在使用Command对象,但您没有参数化违背其目的的值,您可以使用AddWithValue()命令对象上的方法来定义其参数,

string query = "Select Users,Pass from logintable where Users=@user and Pass=@pass";
SqlCommand cmd = new SqlCommand(query, conn);
cmd.Parameters.AddWithValue("@user", txtUser.Text);
cmd.Parameters.AddWithValue("@pass", txtPass.Text);

此外,您可以使用ExecuteScalar()from the Commandobject 而不是使用DataReaderobject 来获取结果的单个值。

试试这个代码片段:

string connStr = "connection string here";
string sqlStatement = @"SELECT COUNT(*) TotalCount
                        FROM logintable 
                        WHERE Users=@user and Pass=@pass";
using (SqlConnection conn = new SqlConnection(connStr))
{
    using(SqlCommand comm = new SqlCommand())
    {
        comm.Connection = conn;
        comm.CommandText = sqlStatement;
        comm.CommandType = CommandType.Text;

        comm.Parameters.AddWithValue("@user", txtUser.Text);
        comm.Parameters.AddWithValue("@pass", txtPass.Text);

        try
        {
            conn.Open();
            int _result = Convert.ToInt32(comm.ExecuteScalar());
            if (_result > 0)
            {
                new Login().Show();
            }
        }
        catch(SqlException e)
        {
            // do something with the exception
            // do not hide it
            // e.Message.ToString()
        }
    }
}

为了正确编码

  • using用于 propr 对象处理的use语句
  • 使用try-catch块来正确处理对象
于 2013-04-17T00:11:31.037 回答
0

您永远不应该使用字符串连接构造 SQL 语句,始终使用参数化查询。请尝试以下代码:

SqlCommand cmd = new SqlCommand("Select Users, Pass from logintable where Users= @Users  AND Pass=@Pass", conn);
cmd.Parameters.Add("@Users", SqlDbType.VarChar, 20);
cmd.Parameters.Add("@Pass", SqlDbType.VarChar, 20);
cmd.Parameters["@Users"].Value = login;
cmd.Parameters["@Pass"].Value = pass;

conn.Open();

SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read()) 
{
   new Login().show();
}
else
{
   lblFail.Text = "Invalid username and password";
}
reader.Close();
reader.Dispose();

conn.Close();
conn.Dispose();

希望这可以帮助。您应该在 try-catch 块中使用上述代码,并在 finally 块中使用 Close/Dispose 调用。

于 2013-04-17T00:18:07.997 回答