我在vb.net中有一个使用mysql作为数据库的应用程序。该应用程序有一个登录表单。还有一个注册表,可以使用bcrypt.net在存档中输入新密码,如本网站所示:
这是我注册新用户的代码(公共程序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
我不确定我是否输错了密码,或者在登录时比较用户名/密码错误。这可能是什么问题?
答案 0 :(得分:1)
问题在于这一行:
If myreader.HasRows = 0 Then
在此代码中,myreader.HasRows
是布尔值,但0
是整数。要进行此比较,必须首先将0
值隐式转换为布尔值。将0
转换为布尔值会导致False
。这意味着如果数据读取器没有返回任何结果,代码将只输入If
块。我相信这与你想要发生的事情相反。相反,只需这样做:
If myreader.HasRows = True Then
或者,甚至更好:
If myreader.HasRows Then
虽然我在这里,但仅仅哈希密码是不够的。您还需要为每个用户设置salt值,并在创建哈希之前将其与密码组合。在对用户进行身份验证时,您会检索该用户名的salt,将其与提供的密码合并,然后将其与结果进行比较。密码比较代码看起来应该更像这样:
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()
函数以允许其他参数,您的插入代码首先生成salt,并且您的数据库表有空间来存储值。
还有一件事......即使这不完全正确。如果你真的想要做得对,你需要确保明文密码只用SecureString对象保存在内存中。
答案 1 :(得分:1)
找到了这种情况的解决方案:
If mydatareader.Hasrows Then
While mydatareader.Read
If (Bcrypt.Net.Bcrypt.Verify(txtPassword.text, mydatareader.Item("password"))) then
MsgBox("Valid Credentials")
else
MsgBox("Invalid Credentials")
End if
End While
mydatareader.Close()
End If