@a63826ndrew
Студент, новичок в Python

Что сделано не так?

Здравствуйте!
Есть вот такой код на языке C#, который выполняется при нажатии кнопки на форме:
private void Vhod_Click(object sender, EventArgs e)
        {
            try
            {
                SHA1 hash = new SHA1();
                LoginTextbox = LoginField.Text;
                HashTextbox = hash.Hash(PasswordField.Text);
                RoleTextbox = RoleField.Text;
                SQLiteConnection conn = new SQLiteConnection("Data source = accounts.db");
                conn.Open();
                SQLiteCommand cmd = new SQLiteCommand($"SELECT login,password,role FROM users WHERE login = '{LoginTextbox}' AND password = '{HashTextbox}' AND role = '{RoleTextbox}'", conn);
                SQLiteDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    if (LoginTextbox.Trim() == reader["login"].ToString() && HashTextbox.Trim() == reader["password"].ToString() && RoleTextbox.Trim() == reader["role"].ToString())
                    {
                        if (RoleTextbox == "Администратор")
                        {
                            this.Hide();
                            var MainForm = new MainForm();
                            MainForm.Closed += (s, args) => this.Close();
                            MainForm.Show();
                        }
                        else if (RoleTextbox == "Менеджер")
                        {
                            this.Hide();
                            var MainForm = new MainForm1();
                            MainForm.Closed += (s, args) => this.Close();
                            MainForm.Show();
                        }
                        else if (RoleTextbox == "Бухгалтер")
                        {
                            this.Hide();
                            var MainForm = new MainForm2();
                            MainForm.Closed += (s, args) => this.Close();
                            MainForm.Show();
                        }
                    }
                    else
                    {
                        MessageBox.Show("Неверный логин или пароль! Пожалуйста,повторите попытку. Также возможно, что вы забыли выбрать роль пользователя.", "Ошибка!");
                        LoginField.Text = "";
                        LoginField.Clear();
                        PasswordField.Text = "";
                        PasswordField.Clear();
                        RoleField.Text = "";
                        RoleField.Clear();
                    }
                }
                reader.Close();
                conn.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

С помощью данного кода осуществляестся авторизация
И вот в чем проблема: для случаев, когда пользователь ввел неправильный логин, пароль или роль был написан вот этот кусок:
else
                    {
                        MessageBox.Show("Неверный логин или пароль! Пожалуйста,повторите попытку. Также возможно, что вы забыли выбрать роль пользователя.", "Ошибка!");
                        LoginField.Text = "";
                        LoginField.Clear();
                        PasswordField.Text = "";
                        PasswordField.Clear();
                        RoleField.Text = "";
                        RoleField.Clear();
                    }

Данный кусок выводит сообщение и очищает поля для ввода данных, и если ввести правильные данные, то авторизация пройдет успешно и откроется другая форма, а если данные введены неправильно, то сообщение о неправильно введенных данных не появляется, и я не могу понять в чем причина этого.
Заранее спасибо
  • Вопрос задан
  • 135 просмотров
Пригласить эксперта
Ответы на вопрос 1
FoggyFinder
@FoggyFinder
Дело в том что вы поместили проверку на то, что пользователя с такими параметрами не существует, внутрь цикла while. Сам запрос в случае ошибок ввода просто не вернет никаких данных и выполнение до этой проверки даже не дойдет.

Чтобы избежать подобных проблем советую вынести считывание из БД в отдельный метод.

Что этот метод может возвращать? Как раз то, что мы хотим проверить - а существует ли такой пользователь у нас в системе и какие у него есть права доступа.
Для удобства добавим отдельный класс для хранения и использования в дальнейшем этой информации. Роль лучше хранить не в виде строк, а в виде перечислений - компактней и работать проще.

public enum Role 
    { 
        Admin, 
        Manager,
        Accountant
    }

    public class User
    {
        public User(string login, Role role)
        {
            Login = login;
            Role = role;
        }

        public string Login { get; }

        public Role Role { get; }
    }


Итак, новый метод будет возвращать экземпляр класса User в случае если параметры введены верно и null если такого пользователя нет.
В вашем коде роль пользователь выбирает сам, что кажется немного странным, на мой взгляд, лучше эту проверку памяти опустить.

public static User GetUserOrNull(string login, string password)
{
    using (var connection = new SqliteConnection(connectionString))
    {
        connection.Open();
        using (var command = connection.CreateCommand())
        {
            var query =
                @"SELECT role FROM users 
                    WHERE login = @login AND password = @password";

            command.CommandText = query;
            command.Parameters.AddWithValue("login", login);
            command.Parameters.AddWithValue("password", password);

            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    // GetOrdinal на тот случай если будем возвращать другие значения
                    var role = reader.GetInt32(reader.GetOrdinal("role"));

                    return new User(login, (Role)role);
                }
            }

            return null;
        }
    }
}


сознательно опускаю обработку ошибок и исключений, это остается уже вам.
Также обратите внимание при составлении SQL запроса значения не вставляются через интерполяцию строк а используются параметры.

Теперь обработка будет намного проще и чище - ведь сам запрос будет находится в другом месте.

private void Vhod_Click(object sender, EventArgs e)
{
    try
    {
        SHA1 hash = new SHA1();
        var login = LoginField.Text;
        var pHash = hash.Hash(PasswordField.Text);
        var user = DataBase.GetUserOrNull(login, pHash);
        if (user != null)
        {
            this.Hide();
            var MainForm = new MainForm();
            MainForm.Closed += (s, args) => this.Close();
            MainForm.Show();
        }
        else
        {
            MessageBox.Show("Неверный логин или пароль! Пожалуйста,повторите попытку.", "Ошибка!");
            LoginField.Text = "";
            LoginField.Clear();
            PasswordField.Text = "";
            PasswordField.Clear();
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы