该工作在C#中完成,并带有一个Access数据库进行连接。 目前,我想从表ACCOUNT_T中检索满足用户输入的凭据(用户名,电子邮件,密码)的帐户数。
该表具有3个属性:acc_username VARCHAR(30),acc_email VARCHAR(50)和acc_password VARCHAR(30) 该表只有一个主菜:“ Tester”,“ test@mail.com”,“ TestPass”
我想检查数据库中与用户输入的凭据匹配的行数/主目录数(每个帐户都是唯一的,因此假设没有重复),并使用了下面显示的代码。
//Checks whether the user has entered the correct credentials
//If correct info is entered, redirect user to the Main Menu page
private void Login_Login_Button_Click(object sender, EventArgs e)
{
//Open connection
ADODB.Connection connection = new ADODB.Connection();
connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=main_db;Jet OLEDB:Engine Type=5;";
connection.Open();
//Create command and object
ADODB.Command command = new ADODB.Command();
object rowsAffected;
//Setting up command and parameters
command.ActiveConnection = connection;
command.CommandText = "SELECT COUNT(*) FROM ACCOUNT_T WHERE acc_username = \'@USERNAME\' AND acc_email = \'@EMAIL\' AND acc_password = \'@PASSWORD\'";
command.Parameters.Append(command.CreateParameter("@USERNAME", DataTypeEnum.adVarChar, ParameterDirectionEnum.adParamInput, 200, Login_Username_TextBox.Text));
command.Parameters.Append(command.CreateParameter("@EMAIL", DataTypeEnum.adVarChar, ParameterDirectionEnum.adParamInput, 200, Login_Email_TextBox.Text));
command.Parameters.Append(command.CreateParameter("@PASSWORD", DataTypeEnum.adVarChar, ParameterDirectionEnum.adParamInput, 200, Login_Password_TextBox.Text));
//Execute command and store into RecordSet
ADODB.Recordset recordSet = command.Execute(out rowsAffected);
//Output A
MessageBox.Show(recordSet.RecordCount.ToString());
//Output B
MessageBox.Show(((int)rowsAffected).ToString());
connection.Close();
if ((int)rowsAffected == 1)
{
MainMenu_User_Label.Text = "Logged In As: " + Login_Username_TextBox.Text;
SetupPanel(MainMenu_Panel);
}
else
{
MessageBox.Show("Wrong Credentials.", "Login Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
但是,如上所述,输出A的“ recordSet.RecordCount.ToString()”的值为-1,输出B的“((int)rowsAffected).ToString()”的值为0。无论用户输入是对还是错,输出都是相同的。 (意味着无论用户输入的数据是否已经存在于数据库中,都会给出相同的输出)
代码是否有问题?
答案 0 :(得分:0)
private string ConnectionString {get { return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=main_db;Jet OLEDB:Engine Type=5;"; } };
private void Login_Login_Button_Click(object sender, EventArgs e)
{
string sql = "
SELECT COUNT(*)
FROM ACCOUNT_T
WHERE acc_username = ? AND acc_email = ? AND acc_password = ?";
int rowsAffected = 0;
using (var connection = new OleDbConnection(ConnectionString))
using (var command = new OleDbCommand(sql, connection))
{
// Use OleDbType enum values to match database column types and lengths.
// I have to guess, but you can get exact values from your database.
// Also, OleDb uses positional parameters, rather than names.
// You have to add the parameters in the order they appear in the query string.
command.Parameters.Add("acc_username", OleDbType.VarChar, 200).Value = Login_Username_TextBox.Text;
command.Parameters.Add("acc_email", OleDbType.VarChar, 200).Value = Login_Email_TextBox.Text;
command.Parameters.Add("acc_password", OleDbType.VarChar, 200).Value = Login_Password_TextBox.Text;
cn.Open();
rowsAffected = (int)command.ExecuteScalar();
} //leaving the using block will guarantee the connection is closed, even if an exception is thrown
MessageBox.Show(rowsAffected.ToString());
if (rowsAffected == 1)
{
MainMenu_User_Label.Text = "Logged In As: " + Login_Username_TextBox.Text;
SetupPanel(MainMenu_Panel);
}
else
{
MessageBox.Show("Wrong Credentials.", "Login Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
虽然我在这里,但我还需要提到这是非常差的密码处理。甚至对于简单的个人应用程序或测试应用程序,都无法永远存储这样的密码。即使在学习代码时,这也是做错了太重要的事情之一。问题是人们倾向于重复使用密码,因此,对您简单的测试应用程序的破坏也可能为攻击者提供凭据,从而使他们可以访问更重要的内容。 不要这样做。
相反,您必须为每个用户创建一个唯一的salt(或nonce)值。当用户设置密码时,您将盐添加到新密码之前。然后,使用诸如BCrypt之类的算法创建组合值的加密哈希,然后再次将salt附加到最终值。现在,您仅存储此更改的信息。 从不存储实际密码。当有人尝试登录时,您将检索存储的信息,提取盐,然后对尝试的密码使用相同的过程。现在,您可以比较散列值,而不是原始密码。