How do I get a login form to reject entries with wrong capitalization? - sql

I have the following code so far for a login form taking data from a database:
Dim myconnection As New SqlConnection("server=classified;database=classified")
myconnection.Open()
Dim theQuery As String = " SELECT Username, Password FROM Accounts WHERE (Username = '" & TextBox1.Text & "' ) AND (Password = '" & TextBox2.Text & "')"
Dim repeatChecker As SqlCommand = New SqlCommand(theQuery, myconnection)
'mycommand.ExecuteNonQuery()
Using reader As SqlDataReader = repeatChecker.ExecuteReader()
If reader.HasRows Then
' User already exists
While reader.Read()
If reader("Password") = TextBox2.Text.ToString And reader("Username").ToString = TextBox1.Text Then
MessageBox.Show("Logged in successfully as " & TextBox1.Text, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
Firs.Show()
Me.Close()
'Clear all fields
End If
End While
Else
MessageBox.Show("Invalid username or password.", MsgBoxStyle.Critical)
End If
End Using
myconnection.Close()
If I put in the correct login info but with wrong capitalization, I don't get an acceptance or a rejection, the program just sits there and does nothing. How can I get a denial of a login when the capitalization is wrong?

As written, you really can't discern just a case-mismatch from a query as you've illustrated in this code. If a database is set up for case-sensitivity, a query will fail if two strings don't match even for the difference of a single mismatched character, but it doesn't retain that as a reason for the mismatch anymore than it would for, say "Apple" not matching "Banana."

Please note that, as the commentators of your question stated:
You're vulnerable to SQL-Injection attacks.
You should never store passwords in clear text in your DataBase. Once the DB gets cracked, all credentials are compromised. Not to mention evil DB-admins that might get tempted to misuse those credentials...
Case-Sensitivity in a password is a good thing.
With those things mentioned, if you want to provide your users with the comfort of a not case-sensitive username, just cast the TextBox1.Text as well as the query result for the Username to upper case by changing (Username = '" & TextBox1.Text & "' ) to (UPPER(Username) = '" & TextBox1.Text.ToUpper() & "')

Related

VB.NET database is not in MS Access and login error

I use Microsoft Access to store the data. The register form shows msgbox that the data was saved but there isn't any data stored in the table when I check the table on Microsoft Access. Is it supposed to be like that or did I code wrong?
This is my register code
If PasswordTextBox.Text.Length >= 8 Then
Try
Dim conn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database2.accdb")
Dim insert As String = "Insert into Table1 values('" & NameTextBox.Text & "','" & Staff_IDTextBox.Text & "','" & Phone_NoTextBox.Text & "','" & UsernameTextBox.Text & "','" & PasswordTextBox.Text & "');"
Dim cmd As New OleDbCommand(insert, conn)
conn.Open()
'cmd.ExecuteNonQuery()
MsgBox("Saved")
For Each txt As Control In Me.Controls.OfType(Of TextBox)()
txt.Text = ""
Next
Catch ex As Exception
MsgBox("Error")
End Try
Else
MsgBox("Password must be more than 8 character")
End If
End If
This is my login code
uname = UsernameTextBox.Text
pword = PasswordTextBox.Text
Dim query As String = "Select password From Table1 where name= '" & uname & "';"
Dim dbsource As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database2.accdb"
Dim conn = New OleDbConnection(dbsource)
Dim cmd As New OleDbCommand(query, conn)
conn.Open()
Try
pass = cmd.ExecuteScalar().ToString
Catch ex As Exception
MsgBox("Username does not exit")
End Try
If (pword = pass) Then
MsgBox("Login succeed")
Else
MsgBox("Login failed")
UsernameTextBox.Clear()
PasswordTextBox.Clear()
End If
There is an error at this line
pass = cmd.ExecuteScalar().ToString
It says:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Your "cmd.ExecuteNonQuery" is commented out, so the code will not save anything to the database.
You should close your connection after executing the INSERT command.
By default the table will have auto-numbered field as the first item in the table. You will need to remove this field from your table for that specific INSERT command to work.
Or you may need to use a slightly different INSERT command. It is useful to have auto-numbered ID fields in a table.
You probably should catch the exception and display ex.Message in your message box rather then "Error". The ex.Message will be much more helpful to you in debugging your program.
I have made all of these mistakes in my code at one time or other.
Your Login Code;
1)
You should catch the exception message and display in it a message box. This will make debugging faster.
The actual exception in your code will read "{"No value given for one or more required parameters."}
Your query is incorrect.
You should do the open, query, and close of the connection inside the Try-Catch block. Test for a null password afterwards to determine if the username does not exist.
Two separate answers provided, because you have two very separate questions.
Best wishes...

How to resolve the syntax error in UPDATE statement

What is wrong with this code? I did everything but I still get a
syntax error in UPDATE statement
Dim konfirmasi As String = MsgBox("Yakin data ingin diubah ?", vbQuestion + vbYesNo, "Konfirmasi")
If konfirmasi = vbYes Then
SqlQuery = "Update Tabel_Pengguna set " & _
"Username = '" & txtUsername.Text & "'," & _
"Password ='" & txtPassword.Text & "' where Kode_Pengguna = '" & txtKodePengguna.Text & "'"
CMD = New OleDbCommand(SqlQuery, DB)
CMD.ExecuteNonQuery()
MsgBox("Data berhasil diubah", vbInformation, "Informasi")
To make MsgBox work you would need to use the bitwise Or operator. This function returns a MsgBoxResult not a String. I suggest you change to the .net MessageBox and leave the old VB6 code behind.
Private Sub OPCode()
'Dim konfirmasi As MsgBoxResult = MsgBox("Yakin data ingin diubah ?", vbQuestion Or vbYesNo, "Konfirmasi")
Dim konfirmasi As DialogResult = MessageBox.Show("Yakin data ingin diubah ?", "Konfirmasi", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If konfirmasi = DialogResult.Yes Then
UpdatePengguna(txtUsername.Text, txtPassword.Text, txtKodePengguna.Text)
End If
End Sub
Keep connection local to the method where they are used so they can be closed and disposed with Using...End Using blocks. In this code both the connection and the command are included in the Using block; note the comma at the end of the first line of the Using.
Always use parameters to avoid Sql injection. With OleDb the names of the parameters are ignored but we use descriptive names to make reading the code easier. It is the order that matters. The order that the parameters appear in the Sql statement must match the order which the parameters are added to the parameters collection. You will have to check your database for the correct datatypes and field sizes. I suspect Kode_Pengguna might be a numeric type. If so, be sure the change the datatype of the passed in parameter PenKode.
I believe you are neglecting to open your connection unless your are passing around open connections (be still my heart!). Open the connection at the last minute, directly before the .Execute... and close it as soon as possible with the End Using.
Private Sub UpdatePengguna(UserName As String, Password As String, PenKode As String)
Using cn As New OleDbConnection(ConStr),
cmd As New OleDbCommand("Update Tabel_Pengguna Set [UserName] = #Username, [Password] = #Password Where Kode_Pengguna = #Kode;", cn)
cmd.Parameters.Add("#Username", OleDbType.VarChar, 100).Value = UserName
cmd.Parameters.Add("#Password", OleDbType.VarChar, 100).Value = Password
cmd.Parameters.Add("#Kode", OleDbType.VarChar, 100).Value = PenKode
cn.Open()
cmd.ExecuteNonQuery()
End Using
MessageBox.Show("Data berhasil diubah", "Informasi", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
I really hope you are not saving passwords as plain text.

VB.net SqlDataReader how to show messagebox if GetString function has null value?

I have a login form which I need to check my database whether the user input of email and password matches the database.
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
myConn = New SqlConnection(My.Settings.MySQLData)
myCmd = myConn.CreateCommand
myCmd.CommandText = "SELECT Email FROM dbo.[User]" &
" WHERE Email = '" & tbEmail.Text & "'"
myConn.Open()
myReader = myCmd.ExecuteReader
myReader.Read()
If myReader.IsDBNull(0) Then
MessageBox.Show("The email address input is invalid or does not exist in database.")
ElseIf myReader.GetString(0) <> tbEmail.Text Then
MessageBox.Show("The email address input is invalid or does not exist in database.")
Else
MessageBox.Show("Email address is OK")
End If
myReader.Close()
myConn.Close()
This is only the email portion. I also have a password portion which I have yet to put in.
My code above does not work however. What is the best way to check against database for login?
Use the HasRows property to avoid the requirement to call the Read method of the DataTableReader if there are no rows within the current result set. - Msdn
If reader.HasRows Then
myReader.Read()
Else
MessageBox.Show("no data present")
End If
According to your comment above, the error is:
Invalid attempt to read when no data is present.
This means that the code assumes that at least one record is being returned by the SQL query, but no records are being returned. That is, there is no record matching the WHERE clause conditions.
You should check for the existence of records before trying to read them. When using a SqlDataReader, this is often done by examining the boolean result of the Read() method. For example:
While myReader.Read()
' read the values here, for example:
myReader.GetString(0)
End While
As soon as myReader.Read() evaluates to False, that means no more records are present in the query result. If it evaluates to False on the first attempt, that means there are no records in the query result in the first place.
From the youtube video shown here: https://www.youtube.com/watch?v=iyjGP4fP7IE
The code myReader.HasRows will check against the database with no hassle.
My new code:
myConn = New SqlConnection(My.Settings.MySQLData)
myCmd = myConn.CreateCommand
myCmd.CommandText = "SELECT Email, Password FROM dbo.[User]" &
" WHERE Email = '" & tbEmail.Text & "'" &
" AND Password = '" & tbPassword.Text & "'"
myConn.Open()
myReader = myCmd.ExecuteReader
If myReader.HasRows Then
LoginScreen.Show()
Else
MessageBox.Show("Invalid Email or Password")
End If
myReader.Close()
myConn.Close()

Concatenate database query result to a string

I am trying to take the single result from a SQL query and concatenate it to a string. Using SQL Server and Visual Studios.
Dim Password As SqlDataReader
cmd.CommandText = "Select Password from tblLogin where Username = '" & UsernameTextBox.Text & "' and EmailAddress = '" & EmailAddressTextBox.Text & "'"
Password = cmd.ExecuteReader
EmailMessage.Body = ("Your password is: " & Password)
The error I am getting is that I cannot use the operator & with Password.
The Password variable in your code is a SQLDataReader object, not a string. It can have many values, so you need to get the part you want out of it. (https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2)
If Password.HasRows Then
Do While Password.Read()
EmailMessage.Body = ("Your password is: " & Password.GetString(0))
Loop
Else
Console.WriteLine("No rows found.")
End If
I would also recommend changing the Password SQLDataREader to a different name, just to make it less confusing.

How to salt and hash a password

The code below allows a user to enter user name and password to log in to enter marks of students. SQL data reader verifies the user credentials from the database before authentication takes place. I would be grateful if someone could modify the code by salting and hashing the password.
Dim frm As New MarksEntryFrm
Dim flag As Boolean
flag = False
If cboForm.Text = "" Or cboAcadYear.Text = "" Or cboSubjCode.Text = "" Or txtUserName.Text = "" Or txtPassword.Text = "" Then
MessageBox.Show("Please any of the fields cannot be left blank", "Blank fields", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
cmd = New SqlCommand("Select a.Form,a.AcademicYear,b.SubjectID,b.UserID,b.Password,c.Term from StudentDetails.Programmes a, StudentDetails.Subjects b,RegistrationDetails.Registration c where b.SubjectID='" & cboSubjCode.SelectedItem & "' and b.UserID='" & txtUserName.Text & "' and b.Password='" & txtPassword.Text & "' collate Latin1_General_CS_AS", cn)
cmd.Parameters.AddWithValue("#UserID", txtUserName.Text) 'protects the database from SQL Injection
cmd.Parameters.AddWithValue("#Password", txtPassword.Text) 'protects the database from SQL Injection
dr1 = cmd.ExecuteReader
ctr = ctr + 1
If dr1.Read Then
frm.Show()
ctr = 0
Hide()
ElseIf ctr < 3 Then
MessageBox.Show("Incorrect Subject Code,User Name or Password. Please try again.", "Wrong data entered", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
Else
MsgBox("Unathorized access. Aborting...")
Close()
End If
dr1.Close()
End If
End Sub
P.S. Akaglo, a better way to check if any fields were left empty is to use the String.IsNullOrEmpty() method. Your method will not detect any null or space characters.
Use a parametrized query
Dim cmdText As String = _
"INSERT INTO Customer(UserName, [Password]) VALUES (#UserName,#Password)"
Dim cmd As SqlCommand = New SqlCommand(cmdText, con)
With cmd.Parameters
.Add(New SqlParameter("#UserName", txtUserName.Text))
.Add(New SqlParameter("#Password", txtPassword.Text))
End With
In the .NET membership providers you will get hashing and seeding given by the .NET library which should be implemented correctly. This IMHO is much to prefer for rolling your own solution. There is an introduction to membership here
IF you prefer to make your implementation the seeding and hashing part is not overtly complex. The seeding could be as simple as adding a random string to the original password prior to hashing it. You then store the hash and the seed in the database. When the user provides the password you then simply readd the seed and compare the hashes. Note that when you make random strings for cryptographic purposes you should not rely on Random, but rather go for some cryptographically secure random generator. The System.Security.Cryptography also contains implementations of many suitable hashing algorithms (sha1, sha256 or similar).
Again: In my opinion you should go for a solution using the SqlMembershipProvider to avoid reimplementing security critical stuff.