您好我在我的销售点上做了一个无效按钮。如果选中复选框,则用户必须先键入密码才能继续按钮功能。将打开一个新表单,您将在那里键入密码。但是密码在sql数据库中被加密。我有解密功能,但我无法使其工作。任何帮助将不胜感激,谢谢。
错误是:Additional information: There is no row at position 0.
PS:我还会包含登录代码,可以很好地解密密码。
以下是代码:
密码表单上的确认按钮:
private void btnConfirm_Click(object sender, EventArgs e)
{
using (SqlConnection con = new SqlConnection("Data Source=BENJOPC\\SQLEXPRESS;Initial Catalog=MARISCHELLdatabase;Integrated Security=True"))
{
using (SqlCommand cmd = new SqlCommand("Select Password from UserAccounts where Password = @Password", con))
{
cmd.Parameters.AddWithValue("@Password", txtAdminPassword.Text);
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
string password = dt.Rows[0]["Password"].ToString();
bool flagpassword = EncryptHelper.VerifyHash(txtAdminPassword.Text, "SHA512", password); // code to decrypt password
if (flagpassword == true)
{
this.DialogResult = DialogResult.OK;
}
else
{
MessageBox.Show("Invalid password.");
txtAdminPassword.Clear();
txtAdminPassword.Focus();
}
}
}
}
方法及其在mainform上的调用方式:(工作正常)
public bool voidd()
{
if (cbVoid.Checked == true)
{
POSadminPassword pap = new POSadminPassword();
if (pap.ShowDialog() != DialogResult.OK)
{
return false;
}
}
return true;
}
和
private void btnRemove_Click(object sender, EventArgs e)
{
if (!voidd())
{
return;
}
else
{
//continue code
}
}
使用解密工作登录代码:
private void btnConfirm_Click(object sender, EventArgs e)
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = "Data Source=BENJOPC\\SQLEXPRESS;Initial Catalog=MARISCHELLdatabase;Integrated Security=True";
cn.Open();
SqlCommand cmd = new SqlCommand("Select * from UserAccounts where Username = '" + txtUsername.Text + "' AND Password = '" + txtPassword.Text.Trim() + "'", cn);
SqlDataAdapter adptr = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adptr.Fill(dt);
DataTable ds = new DataTable();
dt = crud.GetDataTable("Select Username, Password, Position , Firstname , Lastname , Status From UserAccounts Where Status = 'Active' ");
string user = "";
string pass = "";
string pos = "";
string name = "";
string Lname = "";
string status = "";
Boolean checker = false;
for (int i = 0; i < dt.Rows.Count; i++)
{
user = dt.Rows[i].ItemArray[0].ToString();
pass = dt.Rows[i].ItemArray[1].ToString();
bool Encryptflag = EncryptHelper.VerifyHash(txtPassword.Text, "SHA512", pass);
pos = dt.Rows[i].ItemArray[2].ToString();
name = dt.Rows[i].ItemArray[3].ToString();
Lname = dt.Rows[i].ItemArray[4].ToString();
status = dt.Rows[i].ItemArray[5].ToString();
if (user.Equals(txtUsername.Text) && Encryptflag == true)
{
// Succesfully login
}
else
{
checker = true;
}
}
if (checker)
{
MessageBox.Show("Please check your username or password.");
txtPassword.Clear();
txtPassword.Focus();
this.Show();
}
}
答案 0 :(得分:1)
您的查询没有返回任何行,因为数据中没有匹配项。数据库存储哈希密码。 (顺便说一下,不能解密。所以你的期望在开始时是假的。)
您只需要通过用户名查询数据库,而不是通过密码查询数据库。因此,请从WHERE
中删除密码条款。 然后您可以继续对输入的密码进行哈希处理,并将该操作的结果与存储在数据库中的值进行比较。
这是设计的。经过哈希处理后,您无法检索原始密码。相反,您散列输入的密码并查看生成的哈希字符串是否与数据中的匹配。如果是这样,那么原始密码也会匹配。
作为旁注,您的代码对SQL注入是开放的。您应该使用query parameters而不是直接执行用户输入,就好像它是代码一样。
编辑:因此,例如,在按用户名选择用户记录时,您将省略密码子句:
SqlCommand cmd = new SqlCommand("Select * from UserAccounts where Username = @Username", cn);
cmd.Parameters.Add("@Username", SqlDbType.NVarChar, 200); // "200" is a guess, use your actual column size and data type
cmd.Parameters["@Username"].Value = txtUsername.Text;
这会拉出与该用户名匹配的用户记录。然后你的逻辑将继续,就像它已经用来散列输入的密码并将其与存储的已经散列的密码进行比较。