Устранение кнопки с помощью кнопки C #

Ошибка входа

Как вы можете видеть, я хочу поймать исключение public SqlDataReader Login ( BELLogin bellog ) { SqlCommand cmd = new SqlCommand (); cmd . Соединение = Кон . getcon (); cmd . CommandType = CommandType . Текст ; cmd . CommandText = "SELECT имя пользователя, пароль FROM tbl_login WHERE username = @Username AND password = @Password" ; cmd . Параметры . AddWithValue ( "@Username" , bellog . Acctname ); cmd . Параметры . AddWithValue ( «@Password» , bellog . Пароль ); SqlDataReader dr = cmd . ExecuteReader (); return dr ; } пользователь подделывает кнопку входа в систему, если в полях нет значений или если они не соответствуют информации в базе данных.

Например: поле не имеет значений, и я один раз нажимаю кнопку «Вход», это говорит об ошибке. После того, как я нажал кнопку «ОК», я снова нажму кнопку «Логин», и теперь он говорит: «ExecuteReader требует открытого и доступного соединения. Текущее состояние подключения закрыто».

Я использую 3-х уровневое приложение для архитектуры Windows.

BEL:

public class BELLogin
{
    public string Acctname { get; set; }
    public string Password { get; set; }
}

БАЛ:

public SqlConnection getcon()
    {
        if (con.State == System.Data.ConnectionState.Closed)
            con.Open();
        else if (con.State == System.Data.ConnectionState.Open)
            con.Close();
        return con;
    }

    public DataTable ExeReader(SqlCommand cmd)
    {
        getcon();
        cmd.Connection = getcon();
        SqlDataReader dr = cmd.ExecuteReader();
        DataTable dt = new DataTable();
        dt.Load(dr);
        return dt;
    }

DBConnection:

private void btn_login_Click(object sender, EventArgs e)
    {
        BELog.Acctname = txb_accName.Text;
        BELog.Password = txb_password.Text;

        SqlDataReader dr;
        dr = BALog.Login(BELog);

        if (txb_accName.Text == "" || txb_password.Text == "")
        {
            MessageBox.Show("Some fields are empty. Please fill up all fields before clicking LOGIN button.", "Login Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            if (dr.HasRows == true)
            {
                dr.Read();
                Inventory Inv = new Inventory();
                Inv.Show();
                this.Hide();
            }
            else
            {
                MessageBox.Show("You have entered your password or account name incorrectly. Please check your password and account name and try again.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        dr.Close();
}

GUI:

public BELLogin Login(BELLogin bellog)
{
    SqlConnection conn = new SqlConnection(connectionsString);
    try
    { 
        using (SqlCommand cmd = new SqlCommand())
        {
           conn.Open();
           cmd.Connection = conn;
           cmd.CommandType = CommandType.Text;
           cmd.CommandText = "SELECT username,password FROM tbl_login WHERE username = @Username AND password = @Password";
           cmd.Parameters.AddWithValue("@Username", bellog.Acctname);
           cmd.Parameters.AddWithValue("@Password", bellog.Password);
           //really this should be in a using as well. 
           //You be better off reading your data 
           //into a class and returnig the class not the reader.
           using (SqlDataReader dr = cmd.ExecuteReader())
           {
               BELLogin obj = new BELLogin();
               while(dr.Read())
               {
                    //populate obj
               }
               return obj;
           }
       }
   }
   finally
   {
       conn.Close();
       conn.Dispose();
   }
}

Вход в систему в порядке, но что, если пользователь подделывает кнопку? Спасибо, что помогли мне: D

c#,.net,sql-server-2014,

0

Ответов: 4


-1 принято

Просто избавитесь от вашего объекта DBConnection, он ничего не делает и просто делает вашу структуру сложной:

private void btn_login_Click(object sender, EventArgs e)
{
     BELog.Acctname = txb_accName.Text;
     BELog.Password = txb_password.Text;

     if (txb_accName.Text == "" || txb_password.Text == "")
     {
         MessageBox.Show("Some fields are empty. Please fill up all fields before clicking LOGIN button.", "Login Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
         //return;
     }
     else
     {
         SqlDataReader dr;
         dr = BALog.Login(BELog);

         if (dr.HasRows == true)
         {
             dr.Read();
             Inventory Inv = new Inventory();
             Inv.Show();
             this.Hide();
         }
         else
         {
             MessageBox.Show("You have entered your password or account name incorrectly. Please check your password and account name and try again.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
         }

          dr.Close();
    }
}

также способ, которым вы его используете, может привести к утечке памяти, поскольку вы явно не используете и не закрываете свои соединения. Всегда удаляйте объекты Sql в C #. Будьте осторожны и с исключениями. Любые исключения в вашем коде не будут закрывать соединение и т. Д. Это приведет к утечке памяти и блокировке соединений


1

Вам нужно изменить свой код в gui следующим образом:

// Поместите код, чтобы получить читатель внутри предложения IDisposable и закройте его в том же предложении SqlConnection. Также в идеале вы должны SqlCommand, если вы столкнетесь. Я добавил его и прокомментировал это.

// Конечно, вам нужно приложить больше усилий, чтобы сделать этот код лучше. Вы доберетесь до этого, когда получите больше опыта. Пока это должно заставить ваше приложение работать.

SqlDataReader

1
  1. Не используйте повторно такие соединения, это плохая практика и ненужная.
  2. Оберните экземпляры всех типов, которые реализуют DataTableиспользование блоков, чтобы ресурсы были освобождены. В вашем случае , , , . using(var connection = new SqlConnection("connectionStringPointerFromAppConfigHere")) using(SqlCommand cmd = new SqlCommand("SELECT username,password FROM tbl_login WHERE username = @Username AND password = @Password", connection)) { connection.Open(); cmd.Parameters.AddWithValue("@Username", bellog.Acctname).SqlDbType = SqlDbType.VarChar; // BAD practice! Use a secure hash instead and store that not the password! cmd.Parameters.AddWithValue("@Password", bellog.Password).SqlDbType = SqlDbType.VarChar; using(SqlDataReader dr = cmd.ExecuteReader()) { if(dr.Read()) return new BELLogin() {Acctname = dr.GetString(0), Password = dr.GetString(1)}; // passed in is same as in datareader } } return null; }private void btn_login_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txb_accName.Text) || string.IsNullOrEmpty(txb_password.Text)) { MessageBox.Show("Some fields are empty. Please fill up all fields before clicking LOGIN button.", "Login Status", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { var manager = new UserManager(); var user = manager.FindLogin(txb_accName.Text, txb_password.Text); if (user != null) { Inventory Inv = new Inventory(); Inv.Show(); this.Hide(); } else { MessageBox.Show("You have entered your password or account name incorrectly. Please check your password and account name and try again.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }btn_login_ClickBALog.Login(BELog)
  3. С точки зрения безопасности вы никогда не должны хранить свои пользовательские пароли (нигде, а не БД, а не файлы, а не реестр и т. Д., Просто не сохраняйте их). Вам нужно сохранить хеш, а не пароль и сравнить хэши
  4. Придерживайтесь ослабления принципа сцепления / высокой сплоченности. По существу выставляйте как можно меньше (особенно детали реализации) из ваших методов / классов, чтобы их можно было легко использовать и изменять. В настоящее время вы обходитесь и обмениваетесь объектами БД, это сделает ваш код хрупким и очень трудно отследить, где проблемы. Вот ваш код с небольшим количеством рефакторинга, обратите внимание, что если у вас есть еще одна проблема с подключением во время входа в систему, теперь будет очень легко выяснить, где это может быть.

    // размещать в новом файле кода public class UserManager {public BELLogin FindLogin (string userName, string password) {if (string.IsNullOrEmpty (имя_пользователя) || string.IsNullOrEmpty (пароль)) возвращает null;

    btn_login_Click

    }

В вашем классе формы входа в систему

    if (txb_accName.Text == "" || txb_password.Text == "")
    {
        MessageBox.Show("Some fields are empty. Please fill up all fields before clicking LOGIN button.", "Login Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }

0

elseКажется, что ваш метод вызывается if перед проверкой наличия каких-либо допустимых значений в текстовом поле имени пользователя и пароля. Просто переместите проверку в начало elseметода и верните, если поля пустые:

return

Код в elseчасти этого ifутверждения может оставаться там, где он есть, а не внутри else. Метод выйдет из-за returnоператора, если в текстовых полях имени пользователя и пароля нет допустимых значений.

Как и другие, вы должны просмотреть свой код, чтобы убедиться, что вы действительно хотите эту структуру; но если вы хотите сохранить его таким образом, это простое решение решит вашу проблему.

C # ,. сеть, SQL-сервер-2014,