Noob4C0des Ответов: 2

Почему я не могу войти в систему даже с правильными учетными данными?


Привет! Я использую Visual Studio 2017. Я хотел сделать форму окна входа в систему с базой данных. Я погуглил и посмотрел много видео на YouTube, где учат, как это сделать. Я следовал инструкциям, но!!! 2 вопроса!!

Что я уже пробовал:

1. Большинство видео делают это именно так:

private void btnLogin_Click(object sender, EventArgs e)
{
    SqlConnection sqlcon = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\run_h\OneDrive\Documents\LoginDB.mdf;Integrated Security=True");
    string query = "SELECT count(*) FROM [tblLogin] WHERE username = ' " +txtUsername.Text.Trim()+ " ' and password = ' " +txtPassword.Text.Trim()+" ' ";
    SqlDataAdapter sda = new SqlDataAdapter(query, sqlcon);
    DataTable dtbl = new DataTable();
    sda.Fill(dtbl);
    if(dtbl.Rows[0][0].ToString() == "1")
    {
        frmMain objfrmMain = new frmMain();
        this.Hide();
        objfrmMain.Show();
    }
    else
     {
        MessageBox.Show("Try again next time.");
    }
}


Проблема: этот метод ^ даст мне результаты оператора else даже после того, как я введу правильные учетные данные. Затем я прочитал некоторые комментарии, и альтернативное решение было-

2. Альтернативное решение:

private void btnLogin_Click(object sender, EventArgs e)
{
    SqlConnection sqlcon = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\run_h\OneDrive\Documents\LoginDB.mdf;Integrated Security=True");
    string query = "SELECT count(*) FROM [tblLogin] WHERE username = ' " +txtUsername.Text.Trim()+ " ' and password = ' " +txtPassword.Text.Trim()+" ' ";
    SqlDataAdapter sda = new SqlDataAdapter(query, sqlcon);
    DataTable dtbl = new DataTable();
    sda.Fill(dtbl);
    if(dtbl.Rows.Count > 0)
    {
        frmMain objfrmMain = new frmMain();
        this.Hide();
        objfrmMain.Show();
    }
    else
     {
        MessageBox.Show("Try again next time.");
    }
}


Проблема: альтернативное решение, позволяющее мне войти в систему и следующая форма появится, когда я не поставил никаких учетных данных, а также, поставив неправильные учетные данные, когда их не должно быть.

----

Я серьезно понятия не имею, как это исправить. Кто-нибудь знает, как это исправить? Я действительно ценю любое руководство. Заранее благодарю вас!!

Видео, за которыми я следил:

Создать окно входа в систему на C# с помощью Sql Server - YouTube[^]

Как создать форму входа в систему на C# с базой данных в Visual Studio?[С Исходным Кодом] - YouTube[^]

----

2 Ответов

Рейтинг:
2

F-ES Sitecore

string query = "SELECT count(*) FROM [tblLogin] WHERE username = ' " +txtUsername.Text.Trim()+ " ' and password = ' " +txtPassword.Text.Trim()+" ' ";


Вам нужно научиться пользоваться отладчиком. Если у вас есть "admin" в txtUsername и "password" в txtPassword и вы запускаете приведенный выше код, используйте отладчик для просмотра содержимого "query". Это будет


SELECT count(*) FROM [tblLogin] WHERE username = ' admin ' and password = ' password '


Пробелы-это тоже символы, они не игнорируются, есть ли у каждого имени пользователя и каждого пароля в вашей системе начальный и конечный пробелы?

' администратор '

это не то же самое, что

"админ"


Рейтинг:
1

OriginalGriff

Если бы я сел и написал "как этого не делать" для входа в систему, этот код мог бы быть перед книгой - так много плохих идей в таком небольшом количестве строк кода ...
Во-первых, я могу обойти вашу защиту паролем по своему желанию и войти в систему как любой пользователь без пароля, просто введя любое имя пользователя, а затем "';--" в качестве моего имени пользователя. Это называется SQL-инъекцией, и она приводит к тому, что пользователи удаляют вашу БД.
Никогда не объединяйте строки для построения команды SQL. Это оставляет вас широко открытыми для случайной или преднамеренной атаки SQL-инъекции, которая может уничтожить всю вашу базу данных. Вместо этого всегда используйте параметризованные запросы.

Когда вы объединяете строки, вы вызываете проблемы, потому что SQL получает такие команды, как:

SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
Цитата, добавленная пользователем, завершает строку в том, что касается SQL, и вы получаете проблемы. Но могло быть и хуже. Если я приду и наберу вместо этого: "x';DROP TABLE MyTable;--", то SQL получит совсем другую команду:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Которые SQL видит как три отдельные команды:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
Совершенно правильный выбор
DROP TABLE MyTable;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

Поэтому всегда используйте параметризованные запросы! Или будьте готовы часто восстанавливать свою БД из резервной копии. Вы ведь регулярно делаете резервные копии, не так ли?
Исправьте это во всем вашем приложении - оставьте один, и это будет "до свидания, детка" для ваших данных.

Во - вторых, никогда не храните пароли в открытом виде- это серьезная угроза безопасности. Здесь есть некоторая информация о том, как это сделать: Хранение паролей: как это сделать.[^]

В-третьих, зачем извлекать столбцы, которые вы не собираетесь использовать? Никогда не использовать SELECT * FROM если вы не хотите все столбцы - это расточительно, и в этом случае ненужно, потому что если вы использовали SELECT COUNT(*) FROM вместо этого вы можете использовать ExecuteScalar вместо DataTable и получить только тот счетчик, который вас интересует напрямую.

В-четвертых, скольким пользователям ваша система позволяет иметь одинаковые имя пользователя и пароль? Потому что если это не будет по крайней мере 2 то вы никогда никого не войдете в систему:
if(dtbl.Rows.Count > 1)