分别检查用户名和密码
正如 Youssef13 所指出的,您的查询同时指定了用户名和密码,然后您还要检查两者的结果。如果密码或用户名错误,查询将不会返回任何结果,RD.Read 将是 false。我建议先验证用户名,然后验证密码。应该通知用户哪个错误,因为这对登录可用性至关重要。
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
sSql = "Select * from tblusers where username = '" & cmbusers.Text & "'"
execSQL(sSql, False)
'Assume we have one record because usernames are unique, can we assume this?
If RD.Read Then
If txtpass.Text = RD(2) Then
MsgBox("Welcome")
Else
MsgBox("Bad Password", MsgBoxStyle.Critical)
End If
Else
MsgBox("Bad Username", MsgBoxStyle.Critical)
End If
End Sub
SQL 注入、处置和其他改进
下面的代码展示了如何将参数用于avoid sql injection、using 语句用于proper object disposal、try/catch 用于读取器异常,以及使用列名而不是索引(不太容易无意中破坏)。
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
Using MySQLConnection As New SqlConnection("<Connection String Here>")
MySQLConnection.Open()
Using cmd As New SqlCommand("Select * from tblusers where username = @Username", MySQLConnection)
cmd.Parameters.Add("Username", SqlDbType.Text).Value = cmbusers.Text
Try
Using RD = cmd.ExecuteReader()
If RD.Read Then
If RD("<NameOfPasswordColumnHere>") = txtpass.Text Then
MsgBox("Welcome")
Else
MsgBox("Bad Password", MsgBoxStyle.Critical)
End If
Else
MsgBox("Bad Username", MsgBoxStyle.Critical)
End If
End Using
Catch ex As InvalidCastException
'Handling Not implemented, throw exception
Throw
Catch ex As SqlException
'Handling Not implemented, throw exception
Throw
Catch ex As InvalidOperationException
'Handling Not implemented, throw exception
Throw
Catch ex As ObjectDisposedException
'Handling Not implemented, throw exception
Throw
Catch ex As IOException
'Handling Not implemented, throw exception
Throw
Catch ex As NullReferenceException
'Handling Not implemented, throw exception
Throw
End Try
End Using
End Using
End Sub
密码安全
此外,您似乎在存储纯文本密码,应该避免这种情况。即使是一个简单的 XOR 密码(如下所示)也是一种改进。有些人可能会争辩说,这给人一种虚假的安全感,但总比没有好。您可以跟进SQLhashing 以及许多其他改进,但不要害怕从一些小的安全步骤开始。例如,TextBox1.UseSystemPasswordChar = True 和 SecureString 等基本预防措施。
Private Function XORString(Text As String, Key As String, Enc As System.Text.Encoding) As String
Dim TextBytes() As Byte
Dim KeyBytes() As Byte
Dim TextByteCount As Long
Dim KeyByteCount As Long
Dim KeyIdx As Long
Dim TextIdx As Long
TextBytes = Enc.GetBytes(Text)
KeyBytes = Enc.GetBytes(Key)
TextByteCount = UBound(TextBytes)
KeyByteCount = UBound(KeyBytes)
For TextIdx = 0 To TextByteCount
TextBytes(TextIdx) = TextBytes(TextIdx) Xor KeyBytes(KeyIdx)
If KeyIdx < KeyByteCount Then
KeyIdx += KeyIdx
Else
KeyIdx = 0
End If
Next TextIdx
XORString = Enc.GetString(TextBytes)
End Function
这样使用...
'Other code here ...
Using RD = cmd.ExecuteReader()
If RD.Read Then
'RD("NameOfPasswordColumn") must contain an XORed value set from XORString("<UsersSavedPassword>", "ThisIsBetterThanNothing", <Correct Encoding Here>)
If XORString(RD("NameOfPasswordColumn"), "ThisIsBetterThanNothing", System.Text.Encoding.Unicode) = txtpass.Text Then
MsgBox("Welcome")
Else
MsgBox("Bad Password", MsgBoxStyle.Critical)
End If
Else
MsgBox("Bad Username", MsgBoxStyle.Critical)
End If
End Using
'... rest of code