0

我在服务器中创建了一个数据库,并通过 MySql 查询浏览器添加了一行进行测试。该行在 PhpMyAdmin 或 MySql 查询浏览器中可见。

但是当我想在我的程序中到达这个表时,它说我没有行(reader.HasRows = false

cs 是PublicVariables类中的连接字符串

这是代码

public static int checkuser(string myuser, string mypass)
{
        try
        {
            using (MySqlConnection conn = new MySqlConnection(PublicVariables.cs))
            {
                string MypassMd5 = MakeMD5(mypass);
                conn.Open();

                if (conn == null)
                    Environment.Exit(0);

                using (MySqlCommand cmd =
                 new MySqlCommand("SELECT username, password " + "FROM Users WHERE username = 'myuser'" ,conn))
                {                        
                    using (MySqlDataReader reader = cmd.ExecuteReader())
                    {
                        //DateTime mytime = DateTime.Now  ;
                        if (reader.HasRows)
                        {
                            if (Convert.ToString(reader["password"]) != MypassMd5)
                            {
                                reader.Close();
                                conn.Close();
                                return -1;
                            }
                            else
                            {
                                PublicVariables.UserId = Convert.ToString(reader["username"]);
                                PublicVariables.UserDegre = Convert.ToInt16(reader["userdegre"]);
                                conn.Close();
                                reader.Close();
                                return 1;
                            }
                        }
                        else
                        {
                            reader.Close();
                            conn.Close();
                            return 2;
                        }
                 }
            }            
       }
   }
   catch (MySqlException ex)
   {
       MessageBox.Show(ex.ToString());
   }

   return 0;
}

我的代码有什么问题?

4

4 回答 4

3

好吧,主要错误在您的命令字符串中,myuser它是一个变量,您不能通过将变量名放在引号内来传递它的值。

new MySqlCommand("SELECT username, password FROM Users WHERE username = 'myuser'" ,conn)

相反,应将此行转换为使用参数化查询

string commandText = "SELECT username, password, userdegre FROM Users WHERE username = @uname"; 
using (MySqlCommand cmd = new MySqlCommand(commandText ,conn)
{
    cmd.Parameters.AddWithValue("@uname", myuser);
    ....

查看您的代码,您在此之后还有另一个错误。您尝试读取 field userdegre,但您的查询未检索到该字段,因此您需要将其添加到检索到的字段列表中。
但是您真正需要知道的唯一字段是userdegre因为您已经知道用户名和密码,因此您可以删除数据读取器并使用 ExecuteScalar 并将用户名和密码作为 WHERE 子句的参数传递。如果您得到任何回报,那么您确定您的用户已通过数据库的身份验证。

string commandText = "SELECT userdegre FROM Users WHERE username = @uname AND Password =@pwd";
using(MySqlCommand cmd = new MySqlCommand( commandText ,conn))
{                        
    cmd.Parameters.AddWithValue("@uname", myuser);
    cmd.Parameters.AddWithValue("@pwd", MypassMd5);
    var result = cmd.ExecuteScalar();
    if(result != null)
    {
          PublicVariables.UserId = myuser;
          PublicVariables.UserDegre = result.ToString();
    }
}
于 2013-10-03T14:19:15.070 回答
2

不要检查reader.HasRows。您需要调用reader.Read(),并检查结果。

另外,一些附带问题:

  1. MD5 对于密码哈希来说非常弱。真的。只是不要为此使用它。将 bcrypt 视为更好的选择。如果您根本不自己编写身份验证代码,那就更好了。寻找一个库来帮助把这些东西弄好……编写认证代码非常容易,它似乎可以工作,通过了你所有的测试,但有一个微妙的缺陷让你在几个月后被黑。
  2. 无需调用conn.Close()。这就是你的using积木的用途。他们为你处理这件事。
  3. 我也会删除 try/catch 。由于您已经将错误条件返回给调用代码,因此我会将其保留为处理错误的地方,以便您的 try/catch 应该处于该级别。
  4. 您正在寻找userdegre不在选择列表中的结果。
  5. 参数化查询是您的朋友。

把它们放在一起,你会得到这个:

public static int checkuser(string myuser, string mypass)
{
    string passHash = BCrypt(mypass); //Need to get bcyrpt library and make the function
    using (MySqlConnection conn = new MySqlConnection(PublicVariables.cs))
    using (MySqlCommand cmd =
                 new MySqlCommand("SELECT username, password, userdegre FROM Users WHERE username = @user" ,conn))
    {
        cmd.Parameters.Add("@user", SqlDbType.NVarChar, 20).Value = myuser;
        conn.Open();

        using (MySqlDataReader reader = cmd.ExecuteReader())
        {
            if (!reader.Read()) return 2;
            if (Convert.ToString(reader["password"]) != MypassMd5) return -1;

            PublicVariables.UserId = Convert.ToString(reader["username"]);
            PublicVariables.UserDegre = Convert.ToInt16(reader["userdegre"]);
            return 1;
        }
    }
}
于 2013-10-03T14:35:58.100 回答
0

在@Joel 和@Steve 的帮助下,最后对于 c# 2008 net 3.5 WORKING COPY 如下:

公共静态int usertrue(字符串myuser,字符串mypass)

    {
        try
        {
            using (MySqlConnection conn = new MySqlConnection(PublicVariables.cs))
            {
                string MypassMd5 = MakeMD5(mypass);

                using (MySqlCommand cmd =
                 new MySqlCommand("SELECT username, password ,userdegre FROM Users WHERE username =  @user",conn))
                {
                    cmd.Parameters.Add("@user", MySqlDbType.VarChar, 15).Value = myuser;
                    conn.Open();
                    using (MySqlDataReader reader = cmd.ExecuteReader())
                    {

                        if (!reader.Read()) return 2;
                        if (Convert.ToString(reader["password"]) != MypassMd5)  return -1;                            {
                        PublicVariables.UserId = Convert.ToString(reader["username"]);
                        PublicVariables.UserDegre = Convert.ToInt16(reader["userdegre"]);
                        return 1;
                     }


                 }
            }            

            }
        }
于 2013-10-04T10:19:15.017 回答
0

我会尝试像这样 new MySqlCommand("SELECT username, password, userdegre " + "FROM Users WHERE username = 'myuser'" ,conn)) 在您的选择语句中添加 userdegre 列名。

于 2013-10-03T14:17:37.463 回答