Dit is geen antwoord op de NullReferenceException
- daar zijn we nog mee bezig in de comments; dit is feedback voor de beveiligingsonderdelen.
Het eerste waar we naar kunnen kijken is SQL-injectie; dit is heel eenvoudig op te lossen - zie hieronder (merk op dat ik ook wat andere dingen heb opgeruimd)
// 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;
}
Nu denk je misschien "dat is te veel code" - zeker; en er zijn tools om daarbij te helpen! Stel dat we bijvoorbeeld het volgende deden:
public class User {
public int Id {get;set;}
public string Email {get;set;}
public string Password {get;set;} // I'll talk about this later
}
We kunnen dan dapper gebruiken en LINQ om al het zware werk voor ons te doen:
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();
}
Dit doet alles je hebt (inclusief het veilig openen en sluiten van de verbinding), maar het doet het netjes en veilig. Als de methode een null
retourneert waarde voor de User
, betekent dit dat er geen overeenkomst is gevonden. Als een niet-null User
instantie wordt geretourneerd - deze moet alle verwachte waarden bevatten, alleen met behulp van op naam gebaseerde conventies (wat betekent:de eigenschapsnamen en kolomnamen komen overeen).
Het is je misschien opgevallen dat de enige code die overblijft eigenlijk bruikbare code is - het is geen saai sanitair. Tools zoals dapper zijn je vriend; gebruik ze.
Eindelijk; wachtwoorden. Bewaar wachtwoorden nooit. Ooit. Niet een keer. Zelfs niet versleuteld. Nooit. Je moet alleen bewaar hashes van wachtwoorden. Dit betekent dat u ze nooit kunt ophalen. In plaats daarvan moet u hashen wat de gebruiker levert en dit vergelijken met de reeds bestaande hash-waarde; als de hashes overeenkomen:dat is een pass. Dit is een ingewikkeld gebied en er zullen aanzienlijke veranderingen nodig zijn, maar u zou dit moeten doen . Dit is belangrijk. Wat je op dit moment hebt, is onzeker.