Using case-sensitive SELECT query for login module - sql

I am developing a Windows Form application using vb.net in VS10 with user management. I am using following code when a user tries to login:
Try
Dim sel As String
sel = "SELECT uid, name, loginid, password, type FROM user_master WHERE loginid = '" & UsernameTextBox.Text & "' AND password = '" & PasswordTextBox.Text & "'"
Dim cnn As New SqlConnection("Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\RSMS_DB.mdf;Integrated Security=True;User Instance=True")
Dim da As New SqlDataAdapter(sel, cnn)
Dim ds As New DataSet()
da.Fill(ds)
If ds.Tables(0).Rows.Count = 0 Then
MsgBox("Wrong Username and Password Combination!", MsgBoxStyle.Critical, "Login Failed")
Else
current_uid = ds.Tables(0).Rows(0)(0)
current_name = ds.Tables(0).Rows(0)(1)
current_loginid = ds.Tables(0).Rows(0)(2)
current_password = ds.Tables(0).Rows(0)(3)
current_type = ds.Tables(0).Rows(0)(4)
MsgBox("Welcome '" & ds.Tables(0).Rows(0)(1) & "'!", MsgBoxStyle.OkOnly, "Login Successful")
Dim upd = "UPDATE user_master SET lastlogin = '" & System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") & "' WHERE uid = " & current_uid & ""
Dim cmd As New SqlCommand(upd, cnn)
cnn.Open()
cmd.ExecuteNonQuery()
If checkboxLoginState.Checked = True Then
cmd.CommandText = "INSERT INTO login_state VALUES('" & current_uid & "', '" & current_name & "', '" & current_loginid & "', '" & current_password & "', '" & current_type & "')"
cmd.ExecuteNonQuery()
End If
cnn.Close()
load_user_permissions(current_uid) 'DISABLING OPTIONS ACCORDING TO USER RIGHTS
Me.Close()
End If
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Database Error")
End Try
All I want to ask is if it is the right method? Is the SELECT Query case sensitive by default?

The SQL Keywords are case-insensitive (SELECT, FROM, WHERE, etc), but are often written in all caps. However in some setups table and column names are case-sensitive. Usually case-sensitive table and column names are the default. If you want to change it then you can change it in a function of the database's collation settings.
Source - And this could also be helpful for you.
If security is important to you then you should hash the passwords - do not save passwords as plain text! You should check out the library libsodium

Related

How to close the sqldatareader within Using statement?

I'd like to use this code to verify if duplication occurs or not before saving the data to the database. How am I supposed to close the sqldatareader? (As what the error shows me)
con.ConnectionString = "Data Source=PC85AAIEw\SQLEXPRESS;Initial Catalog=Student;Integrated Security=True"
cmd.Connection = con
con.Open()
Dim theQuery As String = "SELECT * FROM Profile WHERE RollNo=#RollNo AND Name=#Name"
Dim cmd1 As SqlCommand = New SqlCommand(theQuery, con)
cmd1.Parameters.AddWithValue("#RollNo", TextBox1.Text)
cmd1.Parameters.AddWithValue("#Name", TextBox2.Text)
Using reader As SqlDataReader = cmd1.ExecuteReader()
If reader.HasRows Then
MessageBox.Show("User already registered! Please try again.", "Error", MessageBoxButtons.OK)
Else
cmd.CommandText = "INSERT INTO Profile VALUES ('" & rollno & "' , '" & name & "' , '" & gender & "' , '" & address & "' , '" & phoneno & "' , '" & datereg & "' , '" & faculty & "' , '" & course & "' , '" & semester & "')"
MessageBox.Show("Profile has been successfully registered!", "Thank you", MessageBoxButtons.OK)
i = cmd.ExecuteNonQuery()
End If
End Using
con.Close()
The error are referring to is because you must complete the execution of the data reader before you try to execute another command on the same connection.
Additionally there are some issues with your code:
It is strongly recommended you use and then dispose of SqlConnections as you use them, do not try to reuse these globally in your application. The ado.net SQL Server client library will handle connection pooling for you by default.
You need to use parameters with your insert just like you did on your select.
Do not to use AddWithValue when adding your parameters, instead use the constructor and also specify the sql data type. If RollNo is a number (like integer) then you should pass the value as an integer to your parameter. I assumed it was a string stored in a varchar.
Wrap all types that implement IDisposable in Using statements to ensure resources are always released. (In case any one wants to nitpick, no it is not required for SqlCommand in this case.)
Dim recordExists As Boolean
Using con As SqlConnection = New SqlConnection("Data Source=PC85AAIEw\SQLEXPRESS;Initial Catalog=Student;Integrated Security=True")
Using cmd As SqlCommand = New SqlCommand("SELECT RollNo FROM Profile WHERE RollNo=#RollNo AND Name=#Name", con)
cmd.Parameters.Add("#RollNo", SqlDbType.VarChar).Value = TextBox1.Text
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = TextBox2.Text
con.Open()
Using reader As SqlDataReader = cmd.ExecuteReader()
recordExists = reader.HasRows
End Using
End Using
End Using
If recordExists Then
MessageBox.Show("User already registered! Please try again.", "Error", MessageBoxButtons.OK)
Else
Using con As SqlConnection = New SqlConnection("Data Source=PC85AAIEw\SQLEXPRESS;Initial Catalog=Student;Integrated Security=True")
Using cmd As SqlCommand = New SqlCommand("INSERT INTO Profile (RollNo, Name) VALUES (#RollNo, #Name)", con)
cmd.Parameters.Add("#RollNo", SqlDbType.VarChar).Value = TextBox1.Text
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = TextBox2.Text
con.Open()
cmd.ExecuteNonQuery()
MessageBox.Show("Profile has been successfully registered!", "Thank you", MessageBoxButtons.OK)
End Using
End Using
End If
if you are using using then not need to close. because it internally close all connection. The code would be like this
using(var con=new Sqlconnection("Data Source=PC85AAIEw\SQLEXPRESS;Initial Catalog=Student;Integrated Security=True")){
cmd.Connection = con
con.Open()
Dim theQuery As String = "SELECT * FROM Profile WHERE RollNo=#RollNo AND Name=#Name"
Dim cmd1 As SqlCommand = New SqlCommand(theQuery, con)
cmd1.Parameters.AddWithValue("#RollNo", TextBox1.Text)
cmd1.Parameters.AddWithValue("#Name", TextBox2.Text)
Using reader As SqlDataReader = cmd1.ExecuteReader()
If reader.HasRows Then
MessageBox.Show("User already registered! Please try again.", "Error", MessageBoxButtons.OK)
Else
cmd.CommandText = "INSERT INTO Profile VALUES ('" & rollno & "' , '" & name & "' , '" & gender & "' , '" & address & "' , '" & phoneno & "' , '" & datereg & "' , '" & faculty & "' , '" & course & "' , '" & semester & "')"
MessageBox.Show("Profile has been successfully registered!", "Thank you", MessageBoxButtons.OK)
i = cmd.ExecuteNonQuery()
End If
End Using
con.Close()}

Solve error in update query

I have code that throws an error - I need your help to solve it.
The error is
Syntax error in update statement
My code:
Try
Dim conn As OleDbConnection = New OleDbConnection(My.Resources.ConnectionString)
Dim cmd As OleDbCommand
conn.Open()
Dim Sql As String = "select * from Administretor"
cmd = New OleDbCommand(Sql, conn)
Dim userE, userR As String
userE = txtOldPass.Text
Dim reder As OleDbDataReader = cmd.ExecuteReader()
While reder.Read()
userR = reder.Item(0)
End While
If userE = userR Then
If txtNewPass.Text = txtNewConfromPass.Text And txtNewConfromPass.Text <> "" And txtNewPass.Text <> "" Then
Sql = "UPDATE Administretor SET PASSWORD='" & txtNewPass.Text & " where LogIn_id=" & txtOldPass.Text & ""
Dim cmd0 As OleDbCommand = New OleDbCommand(Sql, conn)
cmd0.ExecuteNonQuery()
Else
MsgBox("Make sure that you have entered new password in both text Box and they both are same...!")
End If
Else
MsgBox("Enter the correct Username")
End If
MsgBox("Done 2")
Catch ex As OleDbException
MsgBox(ex.Message)
End Try
Two errors
"UPDATE Administretor SET PASSWORD='" & txtNewPass.Text & " where LogIn_id=" & txtOldPass.Text & ""
^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
Missing single quote here---+ |
|
LogIn_Id will never equal the old password--------------------------------+
But apart from the simple syntax errors you have a huge SQL injection vulnerability from building the SQL out of pieces including user input.
In this part,
"UPDATE Administretor SET PASSWORD='" & txtNewPass.Text & " where ...
The PASSWORD will have a single quote before it, and no single quote after it.
Change it to:
"UPDATE Administretor SET PASSWORD='" & txtNewPass.Text & "' where ...
Notice the extra single quote here ----------------------------------------^
Add this syntax :
Sql = "UPDATE Administretor SET PASSWORD='" & txtNewPass.Text & " where LogIn_id=" & txtOldPass.Text & ""
Clipboard.SetText(Sql)
The query will be in your clipboard. Run it on SQL(whichever you are using), and see if the query runs smoothly?
Please show us what the query generation holds and what the error it produce when running directly from the SQL.

VB.Net 2013 (VB fail to search the access database)

I have this weird problem when I register using my system I developed in VB.NET, it does not allow me to login(in the login form) using the correct username and password I registered. However, when I manually input the username and password inside the Access database, I manage to login without any problem. Here are the codes of my login and register
Login
conn = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source= C:\Users\lenovo\Documents\Visual Studio 2012\Projects\SDP user interface\SDP user interface\bin\Debug\SCPdatabase.accdb")
conn.Open()
sql = "Select * FROM Members WHERE Username ='" & txtusername.Text & "' AND [Password] ='" & txtpassword.Text & " ' "
cmd = New OleDbCommand(sql, conn)
dr = cmd.ExecuteReader()
If dr.HasRows Then
MessageBox.Show("Login Success")
Me.Hide()
Member_Page.Show()
Member_Page.lblwelcome.Text = "Welcome" & txtusername.Text
Else
MessageBox.Show("Login Failed")
End If
dr.Close()
conn.Close()
Register
Dim flag As Integer
MyConn.Open()
sql = "Insert INTO Members (Username,[IC],Email,PhoneNumber,FullName,[Password],Newsletter) values (' " & txtusername3.Text & "','" & txtic3.Text & "','" & txtemail3.Text & "','" & txtphone3.Text & "','" & txtname3.Text & "', ' " & txtpwd3.Text & " ',' " & cmb3.Text & " ')"
cmd = New OleDbCommand(sql, MyConn)
flag = cmd.ExecuteNonQuery()
If flag > 0 Then
MessageBox.Show(flag & " records added", "Add Records Successful", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
MyConn.Close() 'closes the connection
Please advice thnx
Your INSERT statement is adding whitespace characters to the values:
' " & txtusername3.Text & "'
^--- here
and
' " & txtpwd3.Text & " '
^--- here ^--- here
etc.
But then when you select from the table, you don't include them:
WHERE Username ='" & txtusername.Text & "' AND [Password] ='" & txtpassword.Text & " '
just here ---^
Get rid of the whitespace characters entirely, as they're changing the values from what you expect those values to be.
Or, better yet, use query parameters so you don't have to manually build these string values in the first place. (And, as a bonus, would close the enormous SQL injection vulnerability you currently have.)

How to Update Password

I'm trying to change a password. Can you look for this and tell what's wrong? Some times I get a Syntax error in the UPDATE statement or even it is working the password didn't change in database. Here's my code:
Dim sqlquery As String = "UPDATE tblLogin SET pword = ? WHERE pword = '" & txtnewpass.Text & "' "
Dim sqlcmd As New OleDbCommand(sqlquery, con)
sqlcmd.Parameters.AddWithValue("#pword", txtnewpass.Text)
con.Open()
sqlcmd.ExecuteNonQuery()
con.Close()
MessageBox.Show("Your password has been changed", "Change Password", MessageBoxButtons.OK, MessageBoxIcon.Information)
Thank you for your help
I don't know VB and VB SQL Syntax by heart, but a Quick Look at your code shows that there are at least two mistakes.
"UPDATE tblLogin SET pword = ?
should be
"UPDATE tblLogin SET pword = #pword
The
WHERE pword = '" & txtnewpass.Text & "' "
should be
WHERE pword = '" & txtoldpass.Text & "' "
Or make it with #param as well. You are trying to change password which doesn't exists yet.
Besides that, passwords should be encrypted in the database, and you shouldn't match (where clause) just by password. What if 2 users have the same password? You will change both user's passwords;)

SQL injection-proofing TextBoxes

I've found some tutorials on this already, but they aren't exactly what I'm looking for, I can use the following for username fields and password fields
Private Sub UsernameTextBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles UsernameTextBox.KeyPress
If Char.IsDigit(e.KeyChar) OrElse Char.IsControl(e.KeyChar) OrElse Char.IsLetter(e.KeyChar) Then
e.Handled = False
Else
e.Handled = True
End If
End Sub
But for an email field how would I go about protecting against SQL injection for that textbox, as some email accounts have periods or dashes in them?
Update:
Below is an example of an insert statement I use.
Dim con As SqlConnection
con = New SqlConnection()
Dim cmd As New SqlCommand
Try
con.ConnectionString = "Data Source=" & Server & ";Initial Catalog=" & Database & ";User ID=" & User & ";Password=" & Password & ";"
con.Open()
cmd.Connection = con
cmd.CommandText = "INSERT INTO TB_User(STRUserID, password, Email) VALUES('" & UsernameTextBox.Text & "', '" & MD5Hash(PasswordTextBox.Text) & "', '" & EmailTextBox.Text & "')"
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Error while inserting record on table..." & ex.Message, "Insert Records")
Finally
con.Close()
End Try
So I need to run this with parametrized queries rather than how I'm doing it now?
Instead of filtering out "invalid" data from user input, consider using parametrized queries and not putting user input directly into your queries; that's very bad form.
To run your current query using parameters, it's pretty easy:
Dim con As New SqlConnection()
Dim cmd As New SqlCommand()
Try
con.ConnectionString = "Data Source=" & Server & ";Initial Catalog=" & Database & ";User ID=" & User & ";Password=" & Password & ";"
con.Open()
cmd.Connection = con
cmd.CommandText = "INSERT INTO TB_User(STRUserID, password, Email) VALUES(#username, #password, #email)"
cmd.Parameters.Add("#username", SqlDbType.VarChar, 50).Value = UsernameTextBox.Text
cmd.Parameters.Add("#password", SqlDbType.Char, 32).Value = MD5Hash(PasswordTextBox.Text)
cmd.Parameters.Add("#email", SqlDbType.VarChar, 50).Value = EmailTextBox.Text
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Error while inserting record on table..." & ex.Message, "Insert Records")
Finally
con.Close()
End Try
All you have to do is use cmd.Parameters.Add with a parameter name and the right database type (the ones I guessed probably don't match up, so you'll want to change them), then set the value to the value you want used in the query. Parameter names start with an #.
It doesn't depend on the textbox. Don't compose a sql sentence joining strings like this:
"SELECT * FROM User WHERE UserName=" + tbName.Text + ...
Use stored procedures or parameterized queries and you'll be safe from SQL injection.
When you use parameters, the textbox content is used as a value, so it doesn't matter what it contains.
Use a parametrized query like this:
Using conn = New SqlConnection("some connection string")
Using cmd = New SqlCommand("SELECT Password FROM tblUser WHERE UserName = #Name", conn)
cmd.Parameters.Add(New SqlParameter("Name", UsernameTextBox.Text))
conn.Open()
Dim password As String = DirectCast(cmd.ExecuteScalar(), String)
Console.WriteLine(password)
End Using
End Using
This is injection safe!