我在 vb.net 中有一个使用 mysql 作为数据库的应用程序。该应用程序有一个登录表单。还有一个注册表单,可以使用 bcrypt.net 在存档中输入新密码,如本网站所示:
这是我注册新用户的代码(公共(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/