Index was out of bound array exeption in Mysql - mysql

I have MySQL table for storing user details which contain 3 columns namely "UserName" ,"password" ,"Access Level". when i try to load details in to VB.net variables it shows " Index was out of bound arrray" Exeption
I am new to mysql please help
I have tried to change the index value of mysqldatareader()
DBConnectionMySql()
myCommandMySql.Connection = myConnectionMySql
myConnectionMySql.Open()
'-----
myCommandMySql.CommandText = "select * from tbl_userregistration where UserName = '" & Trim(Username_TextBox.Text) & "'"
myDataReaderMySql = myCommandMySql.ExecuteReader
If myDataReaderMySql.Read() = Nothing Then
MessageBox.Show("Invalide User Name you Enter!", "Username/Password checker", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Username_TextBox.Focus()
Else
If Username_TextBox.Text = myDataReaderMySql(1) And Password_TextBox.Text = myDataReaderMySql(2) Then
user = Username_TextBox.Text
username = Username_TextBox.Text
Weighing_frm.Show()
Me.Visible = False
Me.Refresh()
Else
MessageBox.Show("Invalide Username Or Password please check and Re-Login!", "Username/Password checker", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Username_TextBox.Focus()
when i try to log in in vb.net form from the loaded data "Index was outside the bounds of the array" error message was shown

Keep you data objects local so you can be sure they are closed and disposed. A Using...End Using block ensures this even if there is an error. You can make your connection string a form level variable so you can use it anywhere but that is the only form level variable you need.
You can pass your connection string directly to the constructor of the connection.
You can pass your sql command text and the connection directly to the constructor of the command.
Please always use Parameters. Not only will it save you from misplacing quotes but it will help ensure that correct datatypes are sent to the database. The most important thing is it helps protect you database from sql injection which can destroy your database. I had to guess at the datatypes in your database. Check the database and adjust the code accordingly.
The DataReader.Read method returns a Boolean so, checking if it returns Nothing is not a valid test. Boolean is a value type so it always returns True or False, never Nothing.
The username is always going to match because that is what you sent to the database in the where clause. As noted in comments by #Jimi, the indexes for the fields returned by the data reader start at 0 so, username would be 0, password 1 and, access level 2. Almost all collections in .net start at index 0.
Why are you using 2 different variables with the same value?
user = Username_TextBox.Text
username = Username_TextBox.Text
What is this supposed to do?
Me.Refresh()
In a real application you would NEVER store passwords as plain text. They would be salted and hashed.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using cn As New MySqlConnection("Your connection string")
Using cmd As New MySqlCommand("select * from tbl_userregistration where UserName = #UserName;", cn)
cmd.Parameters.Add("#UserName", MySqlDbType.Text).Value = Trim(Username_TextBox.Text)
cn.Open()
Using dr = cmd.ExecuteReader
If dr.HasRows Then
dr.Read()
If Password_TextBox.Text = myDataReaderMySql(1) Then
user = Username_TextBox.Text
Weighing_frm.Show()
Me.Visible = False
Else
MessageBox.Show("Invalide Username Or Password please check and Re-Login!", "Username/Password checker", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Username_TextBox.Focus()
End If
Else
MessageBox.Show("Invalid User Name you Enter!", "Username/Password checker", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Username_TextBox.Focus()
End If
End Using
End Using
End Using
End Sub

Related

How can I get the usernames in the account?

I'm making a VB.Net application which connects to a MySql database.
My application has many Accounts, and each account has several Users. I want to show this information, but the application just shows the first user of each account.
This is the code:
Public Function id(Label2 As String) As Double
Using connection = Getconnection()
connection.Open()
Using commandid = New MySqlCommand
commandid.Connection = connection
commandid.CommandText = "SELECT *FROM player.player
Where player.account_id=" & testString & V
Dim read = commandid.ExecuteReader
If read.HasRows Then
While read.Read
ActivateUser.namecharacter = read.GetString(2)
ActivateUser.job = read.GetString(3)
End While
read.Dispose()
Return True
Else
MessageBox.Show(" no ")
Return False
End If
connection.Close()
connection.Dispose()
End Using
End Using
End Function
How can I fix this to show all the users in the account?
Just create you connection in the method where you use it. Get rid of GetConnection just use a class level variable for the connection string.
Don't open a connection until directly before you use it.
You can include the command in the same using block by adding a comma at the end of the first line. Commands also need to be disposed. The command constructor can take the CommandText and the Connection as parameters.
What datatype is account_id in the database? I am going to guess it is a string type. Is V a variable or is it meant to be the string "V"? I am going to guess a hardcoded string. Where does testString come from? I am going to guess Label2 (terrible non-descriptive name) is teststring.
Never concatenate strings for you sql. Always use parameters.
A reader also needs to be closed and disposed so use Using blocks. The whole idea of accessing the database is to get in and out as quickly as possible. Don't set properties of ActivateUser and never show a message box. The user could have gone to lunch and your connection is left flapping in the breeze.
You have the datatype of your function as Double but your return statements have Booleans. Won't work.
It is not necessary to close and dispose the connection. The End Using does that.
Private ConStr As String = "Your connection string"
Public Function id(Label2 As String) As DataTable
Dim dt As New DataTable
Using connection As New MySqlConnection(ConStr),
commandid As New MySqlCommand("SELECT *FROM player Where account_id= #TestString;", connection)
commandid.Parameters.Add("#TestString", MySqlDbType.VarChar).Value = Label2 & "V"
connection.Open()
Using reader = commandid.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Then back in the User Interface code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dt = id(Label2.Text)
If dt.Rows.Count > 0 Then
ActivateUser.namecharacter = dt(0)(2).ToString
ActivateUser.job = dt(0)(3).ToString
Else
MessageBox.Show(" no ")
End If
End Sub
This makes a good separation of from your database code.

BCrypt generate hash and salt then compare to MySQL database

I'm looking to BCrypt to hash and salt and compare it to the hash stored in my database. There seems to be a lack of vb.net with BCrypt, which is why I'm asking.
So, from what I understand is we generate a hash and a salt when the user enters their password. Then we compare that hash to the one in the database, however since I've found nothing online for vb.net I'm not sure how to do it.
This is what I have so far. If the code looks messy it's because I copied and pasted it from Visual Studio to here, on VS it looks neat and tidy.
Now I know there will be flaws with the code etc. I'm not that bothered as this is for personal use and learning. Just need to learn how to generate salt + hash with BCrypt and then compare it with the already hash & salted password in my database but in terms of how to go about and redo this bit of code and implement the check that both salt & hashes are the same I'm stuck.
Dim pw As String = TextBox_Password.Text
Dim Salt As String = BCrypt.Net.BCrypt.GenerateSalt(12)
Dim Hash As String = BCryot.Net.BCrypt.HashPassword(pw, salt)
Try
Connection.Open()
Dim SQLQuery
SQLQuery = "SELECT * FROM `core_members` where name='" & TextBox_Username & " ' and members_pass_hash='" & I don't know if you're meant to put Hash? here to hash the inputed password from the user? Or the TextBox_Password.Text & "'"
'As for the verify function... to compare the hashed password I do try to do this
If (BCRYpt.Net.BCrypt.Verify(pw, hash)) Then
Command1 = New MySqlCommand(SQLQuery, Connection)
READER = Command1.ExecuteReader
Dim Count As Integer
count = 0
While READER.read
count += 1
end while
READER.close()
If count = 1 then
'User Successfully Logged In
end if
'I definitely know the count = 1 etc probably not the best way to allow a user to login. I've seen something with MyData.HasRows or something like that to login?
'I know that the code above is probably no where near close to actually how it's done but as I said due to the lack of documentation with vb.net and BCrypt not making it easy.
Any help with cleaning up the login function would be great including comparing the hashed password in my database.
Just want to give the biggest thanks to #Mary for being so kind and helpful for providing a solution to solve my biggest problem thus far! Thank you!
I'm only making this Answer because for me there were a few typo's I had to fix, but all of it goes to Mary!
So, first off I'm using a mysql.dat.dll which uses Imports MySql.Data.MySqlClient (Which changes a few things from Mary's code)
Imports Crypt = BCRypt.Net.BCrypt - Allows us to use Crypt Instead of having to type the whole BCrypt.Net.BCrypt
Please note for me, if your textbox's are empty then you will get an error Object Reference not set to an instance of an object. This is if you're on visual studio. It won't happen if you run the program as a normal user. I will tell the user make sure they have entered a username and password
Imports Crypt = BCRypt.Net.BCrypt
Private Sub VerifyPassword()
try
Dim Password As String = "TextBox_UserPassword"
Dim Hashword As String = ""
Using Conn As New MySqlCommand(Connection),
Command As New MySqlCommand("SELECT password FROM members where Username= #Username;", Conn)
Command.Parameters.Add("#Username", MySqlDbType.VarChar).Value = TextBox_Username
Conn.Open()
Hashword = Command.ExecuteScalar.ToString
End Using
Dim Result = Crypt.Verify(Password, Hashword)
If result = true then
MsgBox("Logged in")
else
MsgBox("Logged in Failed")
end if
Catch ex As Exception
MessageBox.Show(ex.Message) 'Optional'
MsgBox("Make sure have entered a Username or Password", vbcritical) 'If the textbox have nothing it will remind the user to make sure they enter a username or password'
End try
End Sub
I used Sql Server to test code because it was what I had handy. It will work the same for MySql. With BCrypt you don't have to store the salt separately.
Private Sub InsertNewUser()
Dim HashWord As String = BCrypt.Net.BCrypt.HashPassword(TextBox2.Text, BCrypt.Net.BCrypt.GenerateSalt(12))
Using cn As New SqlConnection(My.Settings.PublishCon),
cmd As New SqlCommand("Insert Into Users (UserName, Password) Values (#Name, #HashWord);", cn)
cmd.Parameters.Add("#Name", SqlDbType.VarChar, 100).Value = TextBox1.Text
cmd.Parameters.Add("#HashWord", SqlDbType.VarChar, 100).Value = HashWord
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
Private Sub VerifyPassword()
Dim pw As String = TextBox2.Text
Dim HashWord As String = ""
Using cn As New SqlConnection(My.Settings.PublishCon),
cmd As New SqlCommand("SELECT Password FROM Users where UserName= #UserName;", cn)
cmd.Parameters.Add("#UserName", SqlDbType.VarChar).Value = TextBox1.Text
cn.Open()
HashWord = cmd.ExecuteScalar.ToString
End Using
Dim result = BCrypt.Net.BCrypt.Verify(pw, HashWord)
If result Then
MessageBox.Show("Successful Login")
Else
MessageBox.Show("Sorry login failed")
End If
End Sub

VB.net and Mysql Login Problem Using Two Tables

How can i login using doctor level in his table.Because everytime i log the receptionist form is always popping even when i log using the user and pass of the doctor maybe my syntax is wrong please help me
PS: Doctors Forms and Receptionists Forms are different.
This is my code:
Try
mycon.Open()
Dim query1 As String
Dim query2 As String
Dim name As String
query1 = "SELECT * FROM receptionisttbl"
command = New MySqlCommand(query1, mycon)
reader = command.ExecuteReader
With reader
.Read()
If .Item("level") = "1" Then
With reader
.Read()
name = .Item("name")
End With
MsgBox("Welcome " + name)
Form1.Show()
command.Dispose()
reader.Close()
mycon.Close()
Else
mycon.Open()
query2 = "SELECT * FROM doctortbl"
command = New MySqlCommand(query2, mycon)
reader = command.ExecuteReader
With reader
.Read()
If .Item("level") = "2" Then
With reader
.Read()
name = .Item("name")
End With
MsgBox("Welcome " + name)
Form2.Show()
command.Dispose()
reader.Close()
mycon.Close()
End If
End With
End If
End With
Catch ex As Exception
MsgBox(ex.ToString)
Finally
mycon.Dispose()
End Try
First, let's consider your requirements.
Provide a login form to validate users.
If the user is valid (userName and matching password are found in the database) then display a Form based on the level of the user.
Considering the requirements look at the design of the table in the database. Let's call it MDUsers.
Now to the columns.
UserName as an VarChar size 100 and Primary key of the table
UserPassword as VarChar size 100
Level an Integer
Now you have fields for all the data you need for your requirements.
Add some sample data to your table.
Next think about what you need from the user to accomplish your requirements. Design your user interface accordingly.
Your login form will have 2 text boxes (userName and password) and a button (Login).
Then you need to think about the code for the Login button.
You need to connect to your database and check if there is a match to userName and password. Once you find a match you only need to retrieve a single piece of data to complete your requirements, the level.
Now how can we ask the database to do all that?
Select level From MDUsers Where userName = #userName And UserPassword = #pword;
Since userName is the Primary Key of the table we know we will find no more than one record with that userName. If the password matches too then we have a valid user and we will return the single piece of data, level for that record.
Using...End Using blocks ensure that your database objects are closed and disposed even if there is an error. You can pass your connection string directly to the constructor of the connection and pass the query string and connection to the constructor of the command.
Always use parameters.
Since we only need a single piece of data we can use .ExecuteScalar
Private Sub OpCode()
Dim retVal As Object
Using cn As New MySqlConnection("Your connection string"),
cmd As New MySqlCommand("Select level From MDUsers Where userName = #userName And UserPassword = #pword;", cn)
cmd.Parameters.Add("#userName", MySqlDbType.VarChar, 100).Value = txtName.Text
cmd.Parameters.Add("#pword", MySqlDbType.VarChar, 100).Value = txtPassword.Text
cn.Open()
retVal = cmd.ExecuteScalar
End Using
If retVal Is Nothing Then
MessageBox.Show("Login failed")
Return
End If
If CInt(retVal) = 1 Then
Form1.Show()
ElseIf CInt(retVal) = 2 Then
Form2.Show()
Else
MessageBox.Show("Level not recognized")
End If
End Sub
You will have to check MySql rules for column names and table names being aware of reserved words.

How to detect same data in a datagridview column?

When a user enters data into the datagrdview, the user cannot enter data that already exists in the datagridview. If the user tries to enter the same data in the datagridview (in the same column), a message box will pop up and tell them: "cannot enter same data on datagridview."
Thank you for your help.
You will need to check the input against the database to see if it is already there. For example, run the following MySQL statement to check if the input is database:
Dim userInput As String
userInput = TextBox1.Text 'an example of user input from a textbox
Dim MySQLStatement As String = "SELECT * FROM `your_table` WHERE your_column = '" & userInput & "';"
I am unable to continue the example above without knowing how you are connecting to the database, but it may be unnecessary. However you connect, you can check the record count after you have executed the MySQL statement. If it is 1 or more, than you know the data is already in your database and you can stop the user input from going into the database.
Finally I've got the solution! This is the code I used to solve the problem. My datagridview name is DataGridView3. The code are :
Private Sub DataGridView3_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView3.CellEndEdit
For Each Row As DataGridViewRow In DataGridView3.Rows
Try
If DataGridView3.Rows(e.RowIndex).Cells(0).Value.ToString <> Row.Cells(0).Value.ToString AndAlso DataGridView3.Rows(e.RowIndex).Cells(0).Value.ToString = DataGridView3.Rows(e.RowIndex).Cells(0).Value.ToString Then
ElseIf DataGridView3.Rows(e.RowIndex).Cells(0).Value.ToString = Row.Cells(0).Value.ToString Then
If Row.Cells(0) Is DataGridView3.Rows(e.RowIndex).Cells(0) Then
Else
MsgBox("Can't Duplicate Condition Data!")
DataGridView3.Rows(e.RowIndex).Cells(0).Value = ""
Exit For
End If
End If
Catch
End Try
Next
End Sub

Invalid attempt to access a field before calling Read() vb.NET and MySQL

I receive this error every time I try log in with incorrect details which should show a message-box "invalid username..." and when no details are entered it should show "please enter...
conn = New MySqlConnection
conn.ConnectionString = "server=localhost; userid=root; password=...; database=..."
Dim reader As MySqlDataReader
Try
conn.Open()
Dim Query As String
Query = "SELECT Username, Password, Admin FROM appointments.tblLogin WHERE Username='" & TextBox_Username.Text & "' AND Password='" & TextBox_Password.Text & "' "
cmd = New MySqlCommand(Query, conn)
reader = cmd.ExecuteReader
Dim count As Integer
count = 0
While reader.Read
count = count + 1
End While
If reader.GetInt32("Admin") = 1 Then
AdminMainMenu.Show()
Me.Hide()
ElseIf reader.GetInt32("Admin") = 0 Then
MainMenu.Show()
Me.Hide()
Else
MessageBox.Show("Invalid username or password")
End If
If TextBox_Username.Text.Equals("") And TextBox_Password.Text.Equals("") Then
MessageBox.Show("Please enter a username and password")
End If
conn.Close()
Catch ex As MySqlException
MessageBox.Show(ex.GetBaseException.ToString)
Finally
conn.Dispose()
End Try
The MySqlDataReader can move forward-only, once it reaches the end of the rows retrieved by the command, it cannot go back to read previous rows.
The loop used to count the number of rows moves the reader to the end of the data stream. So trying to read the Admin field result in an exception.
If TextBox_Username.Text.Equals("") And _
TextBox_Password.Text.Equals("") Then
MessageBox.Show("Please enter a username and password")
Return
End If
.... opening and executing the command code....
If reader.Read Then
Dim isAdmin = (reader.GetInt32("Admin") = 1)
If isAdmin Then
AdminMainMenu.Show()
Me.Hide()
Else Then
MainMenu.Show()
Me.Hide()
End If
Else
MessageBox.Show("Invalid username or password")
End If
conn.Close()
Notice that I have removed the loop and used a simple if/else statement around the Read method to display the error message and I have changed the reading of the Admin flag creating a boolean variable to simplify the logic inside the true part of the if block.
Said that, you need to look at how build parameterized queries because your string concatenation to build the commandtext exposes your program to Sql Injection Attacks (not to mention syntax errors if some of your textbox contains a single quote, try it...)
Consider also that from a security standpoint you should never store passwords in the database in clear text. Use always an hash of the password