我该如何改进我的代码?

时间:2016-04-26 08:22:19

标签: c# sql

昨天我问了一个关于你们帮助很多的桌子的问题。有人建议我不直接存储strConnectionString,所以我改变了我的内容。

这是我的代码:

        private void main_B_login_Click(object sender, RoutedEventArgs e)
    {
        //connect to the database
        SqlConnection loginConn = null;
        SqlCommand cmd = null;
        SqlDataAdapter sda = null;
        DataTable dt = new DataTable();

        loginConn = new SqlConnection("server=localhost;" + "Trusted_Connection=yes;" + "database=Production; " + "connection timeout=30");
        cmd = new SqlCommand("Select Username FROM [User] WHERE Username =@UsernameValue", loginConn);
        loginConn.Open();
        cmd.CommandType = CommandType.Text;
        cmd.Parameters.Add("@UsernameValue", SqlDbType.VarChar).Value = Main_T_Username.Text;
        sda = new SqlDataAdapter(cmd);
        sda.Fill(dt);

        if (dt.Rows.Count > 0)
            {
                //MessageBox.Show("username");

                SqlConnection loginConn2 = null;
                SqlCommand cmd2 = null;
                SqlDataAdapter sda2 = null;
                DataTable dt2 = new DataTable();

                loginConn2 = new SqlConnection("server=localhost;" + "Trusted_Connection=yes;" + "database=Production; " + "connection timeout=30");
                cmd2 = new SqlCommand("Select Password FROM [User] WHERE Password =@PasswordValue", loginConn2);
                loginConn2.Open();
                cmd2.CommandType = CommandType.Text;
                cmd2.Parameters.Add("@PasswordValue", SqlDbType.VarChar).Value = Main_T_Password.Text;
                sda2 = new SqlDataAdapter(cmd2);
                sda2.Fill(dt2);

                if (dt2.Rows.Count > 0)
                {
                    MessageBox.Show("username and Password = Correct");
                }
                else
                {
                    MessageBox.Show("Password = Wrong");
                    loginConn2.Close();
                }

             }
            else
            {
                MessageBox.Show("WrongPass or Username!");
                loginConn.Close();
            }

        }

目前它完美无缺。我不确定两件事。

  1. 现在是连接字符串,因为它在SQL INJECTION方面仍然“不好”吗?

  2. 我的代码基本上先检查用户名然后密码..?我已将它们存储为文本值,因为我不知道如何将其更改为散列。

  3. 我可以简化检查以同时使用用户名和密码吗?但是当用户名错误和密码错误时仍然给出错误?

5 个答案:

答案 0 :(得分:1)

连接字符串不容易sql注入。

您可以像这样检查用户名和密码:

cmd = new SqlCommand("Select Username FROM [User] WHERE Username =@UsernameValue AND Password =@PasswordValue", loginConn);
loginConn.Open();
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("@UsernameValue", SqlDbType.VarChar).Value = Main_T_Username.Text;
cmd2.Parameters.Add("@PasswordValue", SqlDbType.VarChar).Value = Main_T_Password.Text;

答案 1 :(得分:0)

对于连接字符串部分,请使用SqlConnectionStringBuilder类与您的App.Config相结合,而不是直接在代码上使用字符串操作。

Public string GetConnectionString()
{
    //Read the Application Settings from App.Config 
    SqlConnectionStringBuilder sqlConstrBuilder = new SqlConnectionStringBuilder();
    sqlConstrBuilder.DataSource = dataSource;
    sqlConstrBuilder.InitialCatalog = databaseName;
    sqlConstrBuilder.UserID = ConfigurationManager.AppSettings["UserId"].ToString();
    sqlConstrBuilder.Password = ConfigurationManager.AppSettings["Password"].ToString();

    return sqlConstrBuilder.ConnectionString;
}

答案 2 :(得分:0)

  

首先是连接字符串,因为它仍然“坏”   SQL INJECTION?

连接字符串不相关。

您正在使用准备好的 sql语句,这是防止sql注入的好方法。

  

其次我有代码基本上先检查用户名然后   密码..?我把它们都存储为文本值,因为我没有   知道如何将其更改为哈希。

永远不要将密码保存为数据库中的明文

您必须将密码的哈希值保存到DB。 当用户想要登录时,将用户输入的密码的哈希值与DB上存在的密码的哈希值进行比较。

请参阅此处了解一些示例:How to hash a password

  

我可以简化检查以同时使用用户名和密码吗?但是当用户名错误和密码错误时仍然给出错误?

是的,你必须简化它。

目前,当你只想要一个时,你基本上在数据库上进行了两次点击。

您可以通过用户名对数据库进行选择,如果您有0行,则用户名不存在。

否则用户名存在,您可以将用户给您的密码(密码的哈希值)与所选行的密码进行比较(不需要进行第二次选择,您已经从上一个选择)。

这样的事情(改进取决于读者):

   private void main_B_login_Click(object sender, RoutedEventArgs e)
{
    //connect to the database
    SqlConnection loginConn = null;
    SqlCommand cmd = null;
    SqlDataAdapter sda = null;
    DataTable dt = new DataTable();

    loginConn = new SqlConnection("server=localhost;" + "Trusted_Connection=yes;" + "database=Production; " + "connection timeout=30");
    cmd = new SqlCommand("Select Username, Password FROM [User] WHERE Username =@UsernameValue", loginConn);
    loginConn.Open();
    cmd.CommandType = CommandType.Text;
    cmd.Parameters.Add("@UsernameValue", SqlDbType.VarChar).Value = Main_T_Username.Text;
    sda = new SqlDataAdapter(cmd);
    sda.Fill(dt);

    if (dt.Rows.Count > 0)
        {
            if ((string) dt.Rows[0]['Password'] == Main_T_Password.Text)
            {
                MessageBox.Show("username and Password = Correct");
            }
            else
            {
                MessageBox.Show("Password = Wrong");
            }
         }
        else
        {
            MessageBox.Show("WrongPass or Username!");

        }
        loginConn.Close();
    }

答案 3 :(得分:0)

将连接字符串移动到配置文件并使用ConfigurationManager读取它。 Sql Injections不是关于连接字符串,而是关于sql命令。 在代码中编写sql命令并不是一个好习惯,将其移动到存储过程(实际上,对于大多数情况,使用orm更好)。如果你想在代码中保留sql命令,用双引号替换单引号以避免sql注入。

最后,在开始编码之前阅读更多内容。

答案 4 :(得分:0)

您可以做三件事来改进和简化代码:

1 - 将您的配置字符串存储在web.config或App.config

<connectionStrings>
    <add name="ModelDB" connectionString="server=localhost;user id=User;password=Password;port=3333;database=database" providerName="MySql.Data.MySqlClient" />
</connectionStrings>

2 - 将密码存储为数据库byte[]并使用哈希函数(您可以使用System.Security.Cryptography中的MD5)

using System.Security.Cryptography;

byte[] password = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(Main_T_Password.Text));

3 - 使用linq和Ado.Net实体数据模型来简化您的请求 (寻找turotials https://msdn.microsoft.com/en-us/data/ff728653.aspx

然后,您可以从数据库生成C#类,并且您将能够使用linq并将请求中的结果视为对象,这将简化代码。

例如,下面的ModelDB对象将使用Web.configApp.config文件中的connectionString自动连接到mysql数据库。

您可以使用不同的提供程序,具体取决于您的数据库(use providerName="System.Data.SqlClient" if your are using SQLServer

ModelDB sql = new ModelDB();
var users = from users in sql.Users where Username = Main_T_Username.Text select users;

if(users.Count() == 0)
    MessageBox.Show("WrongPass or Username!");
else if(users.Count() > 0 && users[0].Password.SequenceEqual(password))
    MessageBox.Show("username and Password = Correct");
else
    MessageBox.Show("Password = Wrong");