Я пытаюсь изучить C#, и я пишу систему, в которой вам нужно войти в систему, я храню данные в базе данных и загружаю ее с кодом. Данные загружаются без ошибок, я могу Console.WriteLine, и все в порядке, но когда я запускаю сравнение, оно всегда терпит неудачу. Вот соответствующий код.
Обновлено: я пробовал без использования $ в сравнении строк, но он все еще не работает
private void login_button_Click(object sender, EventArgs e)
{
// App.config stores configuration data
// System.Data.SqlClient provides classes
// for accessing a SQL Server DB
// connectionString defines the DB name, and
// other parameters for connecting to the DB
// Configurationmanager provides access to
// config data in App.config
string provider = ConfigurationManager.AppSettings["provider"];
string connectionString = ConfigurationManager.AppSettings["connectionString"];
// DbProviderFactories generates an
// instance of a DbProviderFactory
DbProviderFactory factory = DbProviderFactories.GetFactory(provider);
// The DBConnection represents the DB connection
using (DbConnection connection =
factory.CreateConnection())
{
// Check if a connection was made
if (connection == null)
{
Console.WriteLine("Connection Error");
Console.ReadLine();
return;
}
// The DB data needed to open the correct DB
connection.ConnectionString = connectionString;
// Open the DB connection
connection.Open();
// Allows you to pass queries to the DB
DbCommand command = factory.CreateCommand();
if (command == null)
{
return;
}
// Set the DB connection for commands
command.Connection = connection;
// The query you want to issue
command.CommandText = $"SELECT * FROM Users WHERE Username = '{username_input.Text}'";
// DbDataReader reads the row results
// from the query
using (DbDataReader dataReader = command.ExecuteReader())
{
dataReader.Read();
//while(dataReader.Read())
//{
if ($"{password_input.Text}" ==$"{dataReader["Password"]}")
{
MessageBox.Show("Logged in");
}
else
{
MessageBox.Show("Invalid Credentials!");
}
//}
}
}
}
}
@ gunr2171 дело не в этом, я изучаю C# и то, как взаимодействовать с базами данных, а не как защищать приложения.
посмотрели ли вы в отладчике, что находится в username_input.Text и dataReader ["Password"]
@Throupy, возможно, ваш вопрос не в этом, но, тем не менее, это твердый совет, которому нужно следовать. Развивайте хорошие привычки, а не плохие. Прямо сейчас у вас развивается дурная привычка писать непараметризованные запросы. Научитесь делать это правильно с первого раза.
I am learning C# and how to interact with databases <= тогда вы должны параметризовать свои запросы. Это минимальное усилие.
Хотя мы не можем видеть вашу фактическую модель данных, похоже, вы сравниваете значение текстового поля username со значением password, поступающим из БД ...
а почему не просто старый добрый if (username_input.TExt == dataReader["Password")? Почему сложная строка интерполируется
@SteveDanner Это должен быть password_input, извините, я исправил его сейчас.
@ Игорь Это должен быть password_input, я его поменял. И они точно такие же, когда я смотрю в отладчик
@ pm100 Я тоже это сделал, посмотрим, будет ли разница, с OR без них не работало
Возможно, при сравнении попробуйте использовать Trim() на обеих струнах. Это сожгло меня раньше
Зачем ты делаешь $"{password_input.Text}"? В этом нет необходимости. password_input.Text уже будет строкой, нет необходимости использовать интерполяцию строк.
@ gunr2171, тем не менее, спасибо, что рассказали мне, я разберусь с этим.
@mason да, я пробовал, не повезло :(
ВЫ ОСТАНОВИЛИСЬ НА СТРОКЕ СРАВНЕНИЯ С ОТЛАДЧИКОМ И ПОСМОТРЕЛИ СРАВНИВАЕМЫЕ ЗНАЧЕНИЯ - проблема будет сразу очевидна - извините за крик, но мне нужно было привлечь ваше внимание
@Throupy Что значит "не повезло"? Не нужно везения. Я не говорю вам, как решить вашу проблему, я говорю вам, как очистить ваш синтаксис.
@Throupy, что касается предложения Trim, если ваше поле пароля представляет собой CHAR в базе данных, а не VARCHAR, это БУДЕТ проблемой.
@ pm100 они точно такие же, когда я смотрю в отладчик. Если я делаю это правильно, то это так.
@SteveDanner да, это в nchar в базе данных, сейчас я заменю его на varchar
@Throupy Они не могут быть одинаковыми. Если бы они были, вы бы здесь не задавали этот вопрос. Вы абсолютно уверены, что ни один из них не начинается и не заканчивается пробелом, и что ни один из них не содержит непечатаемых символов Юникода?
Весь этот код ошибочен; это не то, как вводить пароли.
они явно не то же самое. Наиболее вероятные проблемы (как говорили другие) заключаются в том, что у вас есть конечный пробел в одном из значений, поэтому предложение, которое вы делаете для них, Trim
Возможный дубликат Каковы хорошие способы предотвратить SQL-инъекцию?





Начните с правильного пути с изучения C# с некоторыми советами, которые я уже видел в комментариях, а также с некоторыми дополнительными советами ниже:
Параметризуйте свои запросы как минимум Нижеприведенный способ открыт для SQL-инъекции
command.CommandText = $"SELECT * FROM Users WHERE Username = '{username_input.Text}'";
Вместо этого это должно быть записано как: (Имейте в виду, что есть более короткие способы написать это, но я говорю прямо, так как вы учитесь)
var usernameParam = new SqlParameter("username", SqlDbType.VarChar);
usernameParam.Value = username_input.Text;
command.Parameters.Add(usernameParam);
command.CommandText = "SELECT * FROM Users WHERE Username = @username";
Во-вторых, отладка - ваш друг. Вам нужно добавить точку останова в строке, которая не работает, и использовать встроенные в Visual Studio Watchers для просмотра ваших переменных. Это даст вам больше информации, чем console.writeline (), и решит больше проблем, чем вы можете себе представить.
Большое спасибо за ваше время, что касается отладки Visual Studio? Как мне это сделать, я никогда раньше не использовал vs
@Throupy Это не то, о чем стоит просто спрашивать людей. Вместо этого вам следует изучить его. У Microsoft есть много документации по этому поводу, и на YouTube и Channel 9 есть много видео, демонстрирующих использование отладчика Visual Studio.
Это та IDE, которую вы используете? Как новому программисту, вам необходимо провести небольшое исследование, простой поиск в Google «Отладка в Visual Studio» приводит к замечательному ресурсу здесь docs.microsoft.com/en-us/visualstudio/debugger/…
ExecuteScalar упрощает логику (IMO). Если вы хотите вернуть данные и прочитать их с помощью устройства чтения данных, не используйте * для возврата. Вместо этого укажите имена столбцов. Это защитит ваш код от изменений схемы, таких как добавление столбцов или изменение порядка столбцов.command.CommandText = "SELECT [Password] FROM [Users] WHERE [Username] = @userName";
// using DbCommand adds a lot more code than if you were to reference a non abstract implementation when adding parameters
var param = command.CreateParameter();
param.ParameterName = "@userName";
param.Value = username_input.Text;
param.DbType = DbType.String;
param.Size = 100;
command.Parameters.Add(param);
// compared with SqlDbCommand which would be 1 line
// command.Parameters.Add("@userName", SqlDbType.VarChar, 100).Value = username_input.Text;
var result = command.ExecuteScalar()?.ToString();
if (string.Equals(password_input.Text, result, StringComparison.Ordinal))
MessageBox.Show("Logged in");
else
MessageBox.Show("Invalid Credentials!");
Ваш скрипт подвержен риску атак с использованием SQL-инъекций.