Това не е отговор на NullReferenceException
- все още работим по това в коментарите; това е обратна връзка за защитните части.
Първото нещо, което можем да разгледаме, е SQL инжекция; това е много лесно за поправяне - вижте по-долу (обърнете внимание, че съм подредил и някои други неща)
// note: return could be "bool" or some kind of strongly-typed User object
// but I'm not going to change that here
public string[] GetValidUser(string dbUsername, string dbPassword)
{
// no need for the table to be a parameter; the other two should
// be treated as SQL parameters
string query = @"
SELECT id,email,password FROM tbl_user
WHERE [email protected] AND [email protected]";
string[] resultArray = new string[3];
// note: it isn't clear what you expect to happen if the connection
// doesn't open...
if (this.OpenConnection())
{
try // try+finally ensures that we always close what we open
{
using(MySqlCommand cmd = new MySqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("email", dbUserName);
// I'll talk about this one later...
cmd.Parameters.AddWithValue("password", dbPassword);
using(MySqlDataReader dataReader = cmd.ExecuteReader())
{
if (dataReader.Read()) // no need for "while"
// since only 1 row expected
{
// it would be nice to replace this with some kind of User
// object with named properties to return, but...
resultArray[0] = dataReader.GetInt32(0).ToString();
resultArray[1] = dataReader.GetString(1);
resultArray[2] = dataReader.GetString(2);
if(dataReader.Read())
{ // that smells of trouble!
throw new InvalidOperationException(
"Unexpected duplicate user record!");
}
}
}
}
}
finally
{
this.CloseConnection();
}
}
return resultArray;
}
Сега може би си мислите, че "това е твърде много код" - разбира се; и съществуват инструменти, които да помогнат с това! Например, да предположим, че сме направили:
public class User {
public int Id {get;set;}
public string Email {get;set;}
public string Password {get;set;} // I'll talk about this later
}
След това можем да използваме dapper и LINQ, за да вършат цялата работа вместо нас:
public User GetValidUser(string email, string password) {
return connection.Query<User>(@"
SELECT id,email,password FROM tbl_user
WHERE [email protected] AND [email protected]",
new {email, password} // the parameters - names are implicit
).SingleOrDefault();
}
Това прави всичко имате (включително безопасно отваряне и затваряне на връзката), но го прави чисто и безопасно. Ако методът връща null
стойност за User
, това означава, че не е намерено съвпадение. Ако е ненулев User
екземпляр се връща - той трябва да съдържа всички очаквани стойности само като се използват конвенции, базирани на имена (което означава:имената на свойствата и имената на колоните съвпадат).
Може да забележите, че единственият код, който остава, е действително полезен код - не е скучен водопровод. Инструменти като dapper са ваш приятел; използвайте ги.
Накрая; пароли. Никога не трябва да съхранявате пароли. някога. Нито веднъж. Дори не е криптиран. никога. Трябва само съхранявайте хешове на пароли. Това означава, че никога не можете да ги извлечете. Вместо това трябва да хеширате това, което потребителят предоставя и да го сравните със съществуващата хеширана стойност; ако хешовете съвпадат:това е пропуск. Това е сложна област и ще изисква значителни промени, но вие трябва да направите това . Това е важно. Това, което имате в момента, е несигурно.