我有一个用户名的ComboBox和一个用于密码的TextBox。我试图创建通常的登录表单,在用户需要输入正确的用户名和密码,否则访问被拒绝。 MsgBox("欢迎")正在运行,MsgBox("失败")不是。
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
答案 0 :(得分:0)
如果凭据不正确,您的查询将不会返回任何内容,您的messageBox失败位置错误,因为只有在读取数据时它才会出现。
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
答案 1 :(得分:0)
检查用户名和密码分开
正如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