mysql - 无法使用 vb.net 从 mysql 验证 bcrypt-hashed 密码

标签 mysql vb.net authentication bcrypt.net

我在 vb.net 中有一个使用 mysql 作为数据库的应用程序。该应用程序有一个登录表单。还有一个注册表单,可以使用 bcrypt.net 在存档中输入新密码,如本网站所示:

http://derekslager.com/blog/posts/2007/10/bcrypt-dotnet-strong-password-hashing-for-dotnet-and-mono.ashx

这是我注册新用户的代码(公共(public)程序 Clean 用于清理表单):

 Private Sub btSignUp_Click(sender As Object, e As EventArgs) Handles btSignUp.Click
dim hash as string
        hash = HashPassword(txConfirmPass.Text)
        If (txPass.Text <> txConfirmPass.Text) Then
            MessageBox.Show("Passwords don't matches")
        Else
            Dim sql As String = "INSERT INTO fusion_login(name,user,password) VALUES (@name,@user,@pass)"
            Using myconnection As MySqlConnection = Connection.getInstance.getConnection()
                Using mycommand As New MySqlCommand()
                    With mycommand
                        .CommandText = sql
                        .CommandType = CommandType.Text
                        .Connection = myconnection
                        .Parameters.Add("@name", MySqlDbType.VarChar).Value = txName.Text
                        .Parameters.Add("@user", MySqlDbType.VarChar).Value = txUser.Text
                        .Parameters.Add("@pass", MySqlDbType.VarChar).Value = hash
                    End With
                    Try
                        myconnection.Open()
                        mycommand.ExecuteNonQuery()
                        If (MessageBox.Show("Do you insert a new user again?", "Register", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes) Then 
                            Clean(Me)
                        Else
                            Me.Hide()
                            Login.Show()
                        End If
                    Catch ex As MySqlException
                        MessageBox.Show("Error: " + ex.ToString)
                    Finally
                        myconnection.Close()
                    End Try
                End Using
            End Using
        End If
    End Sub

此代码有效!

现在我正在尝试实现对使用上述过程创建的用户进行身份验证的代码,但我无法让它工作。这是我到目前为止所拥有的:

      Private Sub btLogin_Click(sender As Object, e As EventArgs) Handles btLogin.Click
Dim hash as String
hash = HashPassword(txPass.text)
                Dim sql As String = "SELECT  user,password FROM fusion_login WHERE user = @user AND password = @pass"
                Using myconnection As MySqlConnection = Connection.getInstance.getConnection()
                    Using mycommand As New MySqlCommand()
                        With mycommand
                            .CommandText = sql
                            .CommandType = CommandType.Text
                            .Connection = myconnection
                            .Parameters.Add("@user", MySqlDbType.VarChar).Value = txUser.Text
                            .Parameters.Add("@pass", MySqlDbType.VarChar).Value = hash
                        End With
                        Try
    myconnection.Open()
                        myreader = mycommand.ExecuteReader
                        If myreader.HasRows = 0 Then
                            Me.Hide()
                            FusionPrincipal.Show()
                        Else
                            MessageBox.Show("Error", "Login", MessageBoxButtons.OK, MessageBoxIcon.Warning)
                            txUser.Focus()
                        End If

                        Catch ex As MySqlException
                            MessageBox.Show("Error: " + ex.ToString)
                        Finally
                            myconnection.Close()
                            myreader.Close()
                        End Try
                    End Using
                End Using

我不确定我是输入了错误的密码,还是在登录时比较了错误的用户名/密码。这可能是什么问题?

最佳答案

问题是这一行:

If myreader.HasRows = 0 Then

在此代码中,myreader.HasRows 是 bool 值,但 0 是整数。要进行此比较,必须首先将 0 值隐式转换为 bool 值。将 0 转换为 bool 值会导致 False。这意味着如果数据读取器没有返回任何结果,代码只会进入 If block 。我相信这与您想发生的事情相反。相反,只需这样做:

If myreader.HasRows = True Then

或者,甚至更好:

If myreader.HasRows Then

虽然我在这里,但仅仅散列密码是不够的。您还需要为每个用户设置一个盐值,并在创建哈希之前将其与密码结合起来。当您对用户进行身份验证时,您会检索该用户名的加盐值,将其与提供的密码结合起来,然后将其与结果进行比较。密码比较代码应该更像这样:

Public Function AuthenticateUser(ByVal Username As String, ByVal Password As String) As Boolean
    Dim sql As String = "SELECT  user,password,salt FROM fusion_login WHERE user = @user"
    Using myconnection As MySqlConnection = Connection.getInstance.getConnection(), _
          mycommand As New MySqlCommand(sql, myconnection)

        Try
            mycommand.Parameters.Add("@user", MySqlDbType.VarChar).Value = Username
            myconnection.Open()
            Using rdr As MySqlDataReader = mycommand.ExecuteReader()
                If Not rdr.Read() Then Return False
                Return HashPassword(Password, rdr("salt")).Equals(rdr("password"))
            End Using
        Catch 'You probably want to do more here, but "Return False" was enough for this quick example
             Return False
        End Try
    End Using
End Function

当然,您还需要更新 HashPassword() 函数以允许附加参数,您的插入代码首先生成盐,并且您的数据库表有空间存储值。

还有一件事……即使这也不完全正确。如果你真的想做对,你需要确保明文密码只用 SecureString 保存在内存中。对象。

关于mysql - 无法使用 vb.net 从 mysql 验证 bcrypt-hashed 密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29183301/

相关文章:

php - 将多个表中的数据插入到一个单独的表中

mysql - 您好,我已经编写了以下 mysql 查询,但它占用了我太多的 cpu。我该如何优化它

mysql - 查询月份等于的数据库

c# - 仅加载特定操作系统版本的样式

string - 将字符串替换为格式字符串

asp.net - 加密web.config后出错

swift 3 : how to check if cookies for particular URL are configured?

mysql - SQL表设计风格:

php - CakePHP (LDAP) 中的替代身份验证源

图像中的 HTML 元素?