我正在尝试创建一个登录程序,该程序将使用保存在数据库中的用户名和密码来检查用户输入的内容。出于某种原因,程序中的“if(dr.HasRows)”部分无效。当我尝试没有尝试捕获,我得到并错误“可能错误的空声明”。我做错了什么?
SqlConnection Connection = new SqlConnection(@"Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Logins.mdf;Integrated Security=True");
try
{
Connection.Open();
MessageBox.Show("Connection Succesful");
if (Connection != null && Connection.State == ConnectionState.Closed);
SqlCommand cmd = new SqlCommand("SELECT Count(*) FROM Logins WHERE Username='" + txtUsername.Text + "' and Password='" + txtPassword.Text + "'", Connection);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
MessageBox.Show("Login Success");
}
else
{
MessageBox.Show("Incorrect login");
}
}
catch (Exception)
{
MessageBox.Show("Connection Unsuccesful");
}
这条线
if (Connection != null && Connection.State == ConnectionState.Closed);
包含一个导致警告的分号,但是你刚刚打开了连接,添加此检查的目的是什么?
然后是你的字符串连接引起的Sql Injection和解析问题
我会将你的代码更改为
using(SqlConnection Connection = new SqlConnection(....))
{
try
{
Connection.Open();
SqlCommand cmd = new SqlCommand(@"SELECT Count(*) FROM Logins
WHERE Username=@uname and
Password=@pass", Connection);
cmd.Parameters.AddWithValue("@uname", txtUsername.Text);
cmd.Parameters.AddWithValue("@pass", txtPassword.Text);
int result = (int)cmd.ExecuteScalar();
if(result > 0)
MessageBox.Show("Login Success");
else
MessageBox.Show("Incorrect login");
}
catch(Exception ex)
{
MessageBox.Show("Unexpected error:" + ex.Message);
}
}
参数化方法更安全,因为它避免了Sql Injection问题,并将正确引用您的值的工作转移到框架代码。命令文本也更具可读性。
我还将您的代码从ExecuteReader更改为ExecuteScalar,因为您只需要检索查询返回的第一行的第一列,并且不需要SqlDataReader。
我需要说的最后一件事是:捕捉异常只是为了说某些失败并不是一个好习惯。至少,告诉您的用户错误是什么。使用MessageBox.Show("Unexpected error: " + ex.Message)
编辑好抱歉,但我有另一个。以明文形式存储密码确实是一个很大的安全问题。正确的方法是将密码和apply the hashing function的哈希值存储到用于传递密码的参数中,这样只有哈希结果才会传输,如果有人设法偷走了数据库,那将很难恢复到明确的价值观
可能的空语句是:
if (Connection != null && Connection.State == ConnectionState.Closed);
;
最后使if语句毫无意义。
另一方面,您应该使用Parameters传递您的参数,而不是将字符串直接粘贴到查询中以防止SQL注入攻击。
说了这么多,假设连接实际上是有效的,你的if (dr.HasRows)
语句应该仍然正常工作。