当我使用 If/Else 语句时按钮不工作
Button is not working when I used If/Else statement
我有一个用于用户名的组合框和一个用于密码的文本框。我正在尝试创建通常的登录表单,用户需要在其中输入正确的用户名和密码,否则访问将被拒绝。 MsgBox("Welcome") 正在工作,而 MsgBox("Failed") 没有。
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
sSql = "Select * from tblusers where username = '" & cmbusers.Text & "' and password = '" & txtpass.Text & "'"
execSQL(sSql, False)
If RD.Read Then
If cmbusers.Text = RD(1) And txtpass.Text = RD(2) Then
MsgBox("Welcome")
Else
MsgBox("Failed", MsgBoxStyle.Critical)
End If
End If
End Sub
如果凭据不正确,您的查询将不会 return 任何内容,您的 messageBox Failed 位于错误的位置,因为它只有在读取数据时才会出现。
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
sSql = "Select * from tblusers where username = '" & cmbusers.Text & "' and password = '" & txtpass.Text & "'"
execSQL(sSql, False)
If RD.Read Then
If cmbusers.Text = RD(1) And txtpass.Text = RD(2) Then
MsgBox("Welcome")
End If
Else
MsgBox("Failed")
End If
End Sub
检查用户名和密码是否分开
正如 Youssef13 所指出的,您的查询指定了用户名和密码,然后您也检查了两者的结果。如果密码或用户名错误,查询将不会 return 任何结果并且 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
statements for proper object disposal,try/catch
用于 reader 异常,以及列名而不是索引(不太容易被无意中破坏)。
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
我有一个用于用户名的组合框和一个用于密码的文本框。我正在尝试创建通常的登录表单,用户需要在其中输入正确的用户名和密码,否则访问将被拒绝。 MsgBox("Welcome") 正在工作,而 MsgBox("Failed") 没有。
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
sSql = "Select * from tblusers where username = '" & cmbusers.Text & "' and password = '" & txtpass.Text & "'"
execSQL(sSql, False)
If RD.Read Then
If cmbusers.Text = RD(1) And txtpass.Text = RD(2) Then
MsgBox("Welcome")
Else
MsgBox("Failed", MsgBoxStyle.Critical)
End If
End If
End Sub
如果凭据不正确,您的查询将不会 return 任何内容,您的 messageBox Failed 位于错误的位置,因为它只有在读取数据时才会出现。
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
sSql = "Select * from tblusers where username = '" & cmbusers.Text & "' and password = '" & txtpass.Text & "'"
execSQL(sSql, False)
If RD.Read Then
If cmbusers.Text = RD(1) And txtpass.Text = RD(2) Then
MsgBox("Welcome")
End If
Else
MsgBox("Failed")
End If
End Sub
检查用户名和密码是否分开
正如 Youssef13 所指出的,您的查询指定了用户名和密码,然后您也检查了两者的结果。如果密码或用户名错误,查询将不会 return 任何结果并且 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
statements for proper object disposal,try/catch
用于 reader 异常,以及列名而不是索引(不太容易被无意中破坏)。
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