udg*_*gru 1 c# mysql connection
我的MySQL连接抛出了null引用,尽管这段代码在一年前运行良好.
调试器指示异常的行包含
"connection = new MySqlConnection(connectionString);":
DBConnect MySqlConnection = new DBConnect();
string[] resultArray = MySqlConnection.GetValidUser(
"tbl_user",
tbEmail.Text,
tbPassword.Text
);
//THROWS null reference exception in method 'private bool OpenConnection()'
//A first chance exception of type 'System.ArgumentException' occurred in System.Data.dll
Run Code Online (Sandbox Code Playgroud)
这是我的DBConnect类:
class DBConnect
{
private MySqlConnection connection;
private string server;
private string database;
private string uid;
private string password;
public DBConnect()
{
server = "x.x.x.x";
database = "...";
uid = "...";
password = "...";
string connectionString = "SERVER=" + server + ";" +
"DATABASE=" + database + ";" +
"UID=" + uid + ";" +
"PASSWORD=" + password + ";";
connection = new MySqlConnection(connectionString);
}
private bool OpenConnection()
{
try
{
connection.Open();
return true;
}
catch (MySqlException ex)
{
switch (ex.Number)
{
case 0:
MessageBox.Show("Cannot connect to MySQL server.");
break;
case 1045:
MessageBox.Show("Invalid username or password.");
break;
}
return false;
}
}
public string[] GetValidUser(string dbTable, string dbUsername, string dbPassword)
{
string query = "SELECT id,email,password FROM " + dbTable +
" WHERE email='" + dbUsername +
"' AND password='" + dbPassword + "'";
string[] resultArray = new string[3];
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
resultArray[0] = dataReader.GetInt32(0).ToString();
resultArray[1] = dataReader.GetString(1);
resultArray[2] = dataReader.GetString(2);
}
dataReader.Close();
this.CloseConnection();
}
return resultArray;
}
}
Run Code Online (Sandbox Code Playgroud)
可以在此处找到数据库类的原始代码.
这不是答案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=@email AND password=@password";
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;
}
Run Code Online (Sandbox Code Playgroud)
现在,你可能会想"那个代码太多了" - 当然; 和工具有助于此!例如,假设我们做了:
public class User {
public int Id {get;set;}
public string Email {get;set;}
public string Password {get;set;} // I'll talk about this later
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用dapper和LINQ为我们做所有繁重的工作:
public User GetValidUser(string email, string password) {
return connection.Query<User>(@"
SELECT id,email,password FROM tbl_user
WHERE email=@email AND password=@password",
new {email, password} // the parameters - names are implicit
).SingleOrDefault();
}
Run Code Online (Sandbox Code Playgroud)
这可以完成您所拥有的一切(包括安全地打开和关闭连接),但它可以干净安全地完成.如果it方法返回null值User,则表示未找到匹配项.如果User返回非null 实例 - 它应该包含仅使用基于名称的约定的所有期望值(意思是:属性名称和列名称匹配).
您可能会注意到,唯一剩下的代码实际上是有用的代码 - 它不是无聊的管道.像小巧玲珑的工具是你的朋友 ; 使用它们.
最后; 密码.你永远不应该存储密码.永远.从来没有.甚至没有加密.决不.您应该只存储密码的哈希值.这意味着您永远无法检索它们.相反,您应该对用户提供的内容进行哈希处理,并将其与预先存在的哈希值进行比较; 如果哈希匹配:这是一个通行证.这是一个复杂的领域,需要进行重大更改,但您应该这样做.这个很重要.你目前所拥有的是不安全的.
| 归档时间: |
|
| 查看次数: |
2429 次 |
| 最近记录: |