我做的这个表单允许用户更改他们的用户名,密码和/或安全密码,并在XAMPP数据库上连接和更新。我试过在网上看,但我对VB很新,没有什么比这更有意义了。
问题是我可以更改其中任何一个,但是如果我在更改之后尝试更改另一个,我会收到错误: InvalidOperationException未处理 连接必须有效并且打开
错误来自: reader = objcommand.ExecuteReader
这是我的代码:
`导入MySql.Data 导入MySql.Data.MySqlClient
Public Class frmAccountSettings
Private Sub frmAccountSettings_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
objconnection.Open()
objdataadapter.SelectCommand = New MySqlCommand
objdataadapter.SelectCommand.Connection = objconnection
objdataadapter.SelectCommand.CommandText = "Select * FROM Login"
End Sub
Private Sub btnBack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
frmMainMenu.Show()
Me.Hide()
End Sub
Private Sub btnChangeUsername_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChangeUsername.Click
Dim password1, newusername As String
password1 = InputBox("What is the current password?")
sqlstring = "SELECT password FROM Login WHERE Password = '" &
password1 & "'"
objcommand = New MySqlCommand(sqlstring, objconnection)
reader = objcommand.ExecuteReader
If reader.Read Then
reader.Close()
newusername = InputBox("Enter a new username")
sqlstring = "UPDATE `Login` SET `username` = '" & newusername &
"' WHERE `Login`.`password` = '" & password1 & "'"
objdataadapter.SelectCommand.CommandText = sqlstring
objdataadapter.SelectCommand.CommandType = CommandType.Text
objdataset = New DataSet
objdataadapter.Fill(objdataset, "Login")
objconnection.Close()
Else
MsgBox("Incorrect Username. Please make sure your credentials are correct and try again.", MsgBoxStyle.Critical, "Authentication Failed")
reader.Close()
End If
End Sub
Private Sub btnChangePassword_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChangePassword.Click
Dim oldpassword, newpassword1 As String
oldpassword = InputBox("What is the current password?")
sqlstring = "SELECT password FROM Login WHERE Password = '" &
oldpassword & "'"
objcommand = New MySqlCommand(sqlstring, objconnection)
reader = objcommand.ExecuteReader
If reader.Read Then
reader.Close()
newpassword1 = InputBox("Enter a new password")
sqlstring = "UPDATE `Login` SET `password` = '" & newpassword1 &
"' WHERE `Login`.`password` = '" & oldpassword & "'"
objdataadapter.SelectCommand.CommandText = sqlstring
objdataadapter.SelectCommand.CommandType = CommandType.Text
objdataset = New DataSet
objdataadapter.Fill(objdataset, "Login")
objconnection.Close()
Else
MsgBox("Incorrect Password. Please make sure your credentials are correct and try again.", MsgBoxStyle.Critical, "Authentication Failed")
reader.Close()
End If
End Sub
Private Sub btnChangeSecurity_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChangeSecurity.Click
Dim password2, newsecurity As String
password2 = InputBox("What is the current password?")
sqlstring = "SELECT password FROM Login WHERE Password = '" &
password2 & "'"
objcommand = New MySqlCommand(sqlstring, objconnection)
reader = objcommand.ExecuteReader
If reader.Read Then
reader.Close()
newsecurity = InputBox("Enter a new security passphrase")
sqlstring = "UPDATE `Login` SET `security` = '" & newsecurity &
"' WHERE `Login`.`password` = '" & password2 & "'"
objdataadapter.SelectCommand.CommandText = sqlstring
objdataadapter.SelectCommand.CommandType = CommandType.Text
objdataset = New DataSet
objdataadapter.Fill(objdataset, "Login")
objconnection.Close()
Else
MsgBox("Incorrect Password. Please make sure your credentials are correct and try again.", MsgBoxStyle.Critical, "Authentication Failed")
reader.Close()
End If
End Sub
结束课程 `
答案 0 :(得分:0)
我认为您的代码中存在一些错误。最严重的是逻辑缺陷
您无法确定两个用户是否总是选择不同的密码。您需要确保数据条Login
在primary key
字段中有username
,并在查询中使用该字段来唯一标识要更改的记录。此外,更改用作主键的用户名并非易事。您需要检查其他用户是否尚未使用新用户名。如果您的应用程序在共享环境中使用,您还需要考虑并发更改(两个用户决定将其用户名更改为相同的新名称)
此外,适配器的SelectCommand
不是执行数据库更新的适当方法。但是,根本不需要使用适配器来执行这些操作,您可以使用MySqlCommand
执行所有操作。
将密码以明文形式存储在数据表中还有另一个安全问题。您永远不应该这样做,而是应该在将密码存储到表中之前对其使用散列函数。
但是,限制我对当前问题的回答并排除并发问题,我会以这种方式更改您的代码(当然username
应该是主键)...
Dim password1, newusername, oldusername As String
oldusername = InputBox("Type the current username")
password1 = InputBox("What is the current password?")
newusername = InputBox("Enter a new username")
' identify the current user ... '
sqlstring = "SELECT COUNT(*) FROM `Login` WHERE `username` = @uname AND `password` = @pwd"
objcommand = New MySqlCommand(sqlstring, objconnection)
objcommand.Parameters.AddWithValue("@uname", oldusername)
objcommand.Parameters.AddWithValue("@pwd", password1)
Dim result = objcommand.ExecuteScalar
if result IsNot Nothing AndAlso Convert.ToInt32(result) > 0 Then
' we have good credentials, but the new user name should be unique '
sqlstring = "SELECT COUNT(*) FROM `Login` WHERE `username` = @uname"
objcommand = New MySqlCommand(sqlstring, objconnection)
objcommand.Parameters.AddWithValue("@uname", newusername)
Dim result = objcommand.ExecuteScalar
if result Is Nothing OrElse Convert.ToInt32(result) = 0 Then
' we could change the username of the current user '
sqlstring = "UPDATE `Login` SET `username` = @newame WHERE `username` = @oldname"
objcommand = New MySqlCommand(sqlstring, objconnection)
objcommand.Parameters.AddWithValue("@newame", newusername)
objcommand.Parameters.AddWithValue("@oldname", oldusername)
objcommand.ExecuteNonQuery()
else
MessageBox.Show("Username already taken, choose a different one")
End If
Else
MessageBox.Show("Invalid credentials given")
End If
通过这种方式,您可以使用用户和密码的组合来唯一标识数据库中的用户,并更改所涉及的确切记录。
当您想要更改密码字段时,请求用户名和密码,只有在用户名和密码匹配时才更新字段。
编辑根据您上面的评论,如果数据库中只有一个用户,那么您可以直接执行更改而无需任何复杂的检查。 (但这确实是一个不能被认为普遍存在的情况)
sqlstring = "UPDATE `Login` SET `username` = @newame WHERE `password` = @pwd"
objcommand = New MySqlCommand(sqlstring, objconnection)
objcommand.Parameters.AddWithValue("@newame", newusername)
objcommand.Parameters.AddWithValue("@pwd", password1)
objcommand.ExecuteNonQuery()
另一个问题是连接对象。它是一个在Form_Load事件中打开的全局对象,然后一直挂在你的代码上,但在某些地方你关闭它,当你尝试执行另一个数据库操作时,你忘了重新打开。这是一个很好的做法,没有全局用于连接的对象,而是在需要时构建一个,使用它然后将其销毁
例如
Private Sub btnChangeSecurity_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChangeSecurity.Click
Using objconnection = new MySqlConnection(....connectionstring goes here ....)
objconnection.Open()
Dim sqlstring = "UPDATE `Login` SET `username` = @newame WHERE `password` = @pwd"
objcommand = New MySqlCommand(sqlstring, objconnection)
objcommand.Parameters.AddWithValue("@newame", newusername)
objcommand.Parameters.AddWithValue("@pwd", password1)
objcommand.ExecuteNonQuery()
End Using
End Sub
如果将数据库访问代码放在上面的using语句中,则创建连接对象,打开它,使用它,完成后,End Using语句将关闭并销毁连接。