【问题标题】:How to find the forgotten password by WPF from SQL Server?如何从 SQL Server 中找到 WPF 忘记的密码?
【发布时间】:2020-06-15 18:29:09
【问题描述】:

如果正确回答了两个安全问题,我的 WPF 项目中有一个窗口可以帮助用户显示忘记的密码。不幸的是,我的代码不能正常工作,因此我需要你的帮助。

在我的代码中,我尝试从文本框中读取第一个和第二个答案,如果它们与 SQL Server 表中的 S_Question1S_Question2 匹配,那么应该显示Psswrd,将相同的字段写入记录。

非常感谢您的温柔反馈!

我的 XML 代码:

 <StackPanel HorizontalAlignment="Center" 
                            VerticalAlignment="Center"
                            Grid.Row="1">
        <TextBox x:Name="SecurtyQuestionMother" Width="385"/>
        <TextBox x:Name="SecurityQuestionSchool" Width="385" Margin="0 10 0 0"/>
        <StackPanel Orientation="Horizontal" 
                    HorizontalAlignment="Center"
                    Margin="10">
            <Button Name="match" 
                    Content="match" 
                    Width="50"
                    Click="CheckPassword"/>
        </StackPanel>
        <Label x:Name="PasswordApears"/>
    </StackPanel>

后面的代码:

 private void CheckPassword(object sender, RoutedEventArgs e) //updated...
    { 

        SqlConnection conn = new SqlConnection(connectionString);
        string sql = "select * from Ceo where S_Question1 =@one and S_Question2=@two;";
        SqlCommand command = new SqlCommand(sql, conn);
        command.Parameters.AddWithValue("@one", securityQ_mother_textbox.Text).SqlDbType = SqlDbType.Char;
        command.Parameters.AddWithValue("@two", securityQ_school_texbox.Text).SqlDbType = SqlDbType.Char;
        conn.Open();
        SqlDataReader reader = command.ExecuteReader();

        while (reader.Read())
        {
            if ((reader["S_Question1"]).ToString() == securityQ_mother_textbox.Text || reader["S_Question2"].ToString() == SecurityQuestionSchool.Text)
            {
                PasswordApears.Content = $"Password is: {reader["Psswrd"]}"; //PasswordApears <- is a label
            }
            else
            {
                PasswordApears.Content = "Didn't match";
            }
        }
        conn.Close(); }

这是 SQL Server 表:

【问题讨论】:

  • 你能做一些调试并验证问题出在哪里吗?阅读器中的值是否正确?它甚至正确连接到数据库吗? (如果您输入的是小写字母,可能是大小写问题?)(另外,您使用 or 和 not and 进行检查。
  • 非常感谢您的回复,它已连接,但仅显示一个错误(严重性代码描述项目文件行抑制状态警告 CS0108 'AddCustomer.Close' 隐藏继承的成员 'Window.Close()' . 如果要隐藏,请使用新关键字。SoleTrader .......\SoleTrader\Dialogs\AddCustomer.xaml 293 Active )
  • 与您的问题无关,但仅供参考:您存储密码的方式非常不安全。
  • 让我们想想,不是密码,而是另一个字段。
  • 哦...问题是您的 SELECT 语句。您只需选择 Psswrd 字段。所以 reader[6] 不存在。要么对所有字段使用 SELECT *,要么只选择 S_Question、S_Question2,然后是 reader[0] 和 reader[1]。不知道我第一次怎么错过了对不起!您还应该对 ID 字段进行 WHERE 检查,因为这是唯一的。如果您有 2 个用户的安全答案相同,则您无法确定会返回哪一个。

标签: c# xml wpf


【解决方案1】:

真的不是故意的,但你这样做的方式太多错误了。请花点时间阅读这个答案并学习。它会让你成为一个更好的开发者。

密码安全

(安全标准会随着威胁的发展而变化,请确保您了解最新的最佳实践)

切勿存储纯文本密码

地球上没有安全的网站或应用程序会真正存储用户的密码以供身份验证使用。相反,他们会做一些叫做“散列”的事情。散列是一种单向过程,可将输入转换为统计上唯一的乱码输出。这种乱码被称为“哈希”。相同的输入总是产生相同的散列,但散列无法转换回原始输入。

hash 是存储在数据库中的东西,而不是密码。

您可以判断用户是否输入了正确的密码,因为您可以对他们输入的内容进行哈希处理并将其与有效密码的哈希值进行比较。但由于散列是一种单向过程,黑客无法获取散列,然后在发生安全漏洞时使用它来找出用户的密码。

这就是为什么如果您忘记密码,任何安全网站或应用程序都不会向您发送/显示您的密码。 他们实际上并没有它,只有哈希。他们能做的最好的事情就是允许您设置一个新密码来替换旧密码。

注意:这只是一个摘要,根本不是对存储密码等敏感信息的正确技术的完整解释。它遗漏了许多细节(例如“加盐”)。任何使用此类数据的人都应该彻底研究当前的最佳实践。

SQL 注入

切勿将用户输入的文本直接放入 SQL 语句中

您当前正在通过从用户那里获取文本输入并将其直接粘贴到查询字符串中来创建 SQL 查询。您期望用户会输入一个合法的答案,但他们可以输入任何东西否则——包括其他SQL命令。

例如,如果用户将其输入securityQ_mother_textbox

' OR 1=1--

那么你的 SQL 语句会变成:

select Psswrd from Ceo where S_Question1 ='' OR 1=1--' and S_Question2='{two}';

这将返回每条记录。他们还可以轻松添加其他语句,例如 DELETE 并擦除整个数据库。这种类型的恶意输入称为“SQL 注入”,因为攻击者正在将他们的 SQL 代码“注入”到您的应用程序中。

正确的方法是使用参数:

string sql = "select Psswrd from Ceo where S_Question1 = @one and S_Question2= @two;";

...

command.Parameters.AddWithValue("@one", securityQ_mother_textbox.Text).SqlDbType = SqlDbType.NVarChar;
command.Parameters.AddWithValue("@two", securityQ_school_texbox.Text).SqlDbType = SqlDbType.NVarChar;

SqlParameter 类在将输入添加到字符串之前“清理”输入。这意味着它会改变输入,使其不能被解释为变量以外的任何东西。

总是使用变量;永远不要将输入直接放入命令中

IDisposable

Using objects that implement IDisposable

SqlConnectionSqlCommandSqlDataReader 都实现了IDisposable 接口。根据上面链接的文档,这意味着它们应该贴在 using 块中。这也会为您调用conn.Close

代码的实际问题

在您的 SQL 语句中,您只选择了Psswrd 列,这意味着reader 只会返回该列。像 reader[6]reader[7] 这样的调用将失败,因为实际上只有一列可用。

此外,列通常按名称访问,而不是索引(编号)。例如reader["First_Name"]

【讨论】:

  • 嘿 Stein,非常感谢您的热心回复和您的时间投入,非常感谢。自 11 个月以来我一直在做编码,现在我必须为我的学校编写一个 WPF 项目,我尽我所能来发展我的编码知识。反正我也试过你的方法。但遗憾的是仍然没有改变:(,我不知道,if 和 else 语句都不会运行并显示任何反应。我已经更新了问题!
  • Keith 你可能想用我对 SQL 中 where 子句的最新评论来更新你的答案。如果不匹配,则代码不会落入 reader.Read() 中,因此不会显示“不匹配” - WHERE 子句也会使代码中的检查变得多余。
猜你喜欢
  • 1970-01-01
  • 2013-03-06
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 2012-11-28
  • 2016-12-02
  • 2012-07-25
  • 2020-11-13
相关资源
最近更新 更多