sql command query for log in asp.net - sql

Hello i been looking around and i cant seem to find how to make a safe sql command ( vs injections ) for checking log in details from the database , i found something like this code which seem to be the thing i need but i cant seem to understand how to actully check if the user exists.
This code happens on LogIn Button click , and i am suppose to redirect the user to another page + save some of the valuse from the row ( like userId , companyId and few others ) into sessions for later use . I just not so sure how .
Protected Sub enterBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
Dim connectionString As String = ConfigurationManager.ConnectionStrings("ConnectionString").ToString()
Dim query As String = String.Format("select userName, userPassword, companyId from " & "[users] where userName like '%+#userName+%', userBox.Text)
Using con As New SqlConnection(connectionString)
'
' Open the SqlConnection.
'
con.Open()
'
' The following code uses an SqlCommand based on the SqlConnection.
'
Using da As New SqlDataAdapter()
Using command As New SqlCommand(query, con)
'pass the parameter
command.Parameters.Add(New SqlParameter("#userName", userBox.Text))
command.Parameters.Add(New SqlParameter("#userPassword", passwordInput.Text))
command.Parameters.Add(New SqlParameter("#companyId", companyIdBox.Text))
Dim ds As New DataSet()
da.SelectCommand = command
da.Fill(ds, "test")
End Using
End Using
End Using

Change your query string to
Dim query As String = "select userName, userPassword, companyId " & _
"from [users] " & _
"where userName like #userName " & _
"userPassword = #userPassword " & _
"companyID = #companyID"
and then in the section where you add the parameters
command.Parameters.Add(New SqlParameter("#userName", "%" & userBox.Text "%"))
The trick is to write the query text as clean as possible and add the wildcard required by the like directly in the value passed to the SqlParameter constructor
I suggest also to use a different way to build your Parameters collection
command.Parameters.Add(New SqlParameter With
{
.ParameterName = "#userName",
.Value = "%" & userBox.Text "%",
.SqlDbType = SqlDbType.NVarChar
})
This is more verbose but avoids the confusion between the two overloads of the Add method the one that accepts an SqlDbType and the one that accepts an object as second parameter.
Then if you want to know if a user with that name, password an company has been found just loop at the count of rows present in the first table of the DataSet
If ds.Tables(0).Rows.Count > 0 then
... you have your user .....
End if
However a better query would be
Dim query As String = "IF EXISTS(select 1 from [users] " & _
"where userName like #userName " & _
"userPassword = #userPassword " & _
"companyID = #companyID) " & _
"SELECT 1 ELSE SELECT 0"
and instead of the SqlDataAdapter and DataSet you write simply
Using con As New SqlConnection(connectionString)
Using command As New SqlCommand(query, con)
con.Open()
command.Parameters.Add(New SqlParameter("#userName", userBox.Text))
command.Parameters.Add(New SqlParameter("#userPassword", passwordInput.Text))
command.Parameters.Add(New SqlParameter("#companyId", companyIdBox.Text))
Dim userExists = Convert.ToInt32(command.ExecuteScalar())
if userExists = 1 Then
Session["UserValidated"] = "Yes"
else
Session["UserValidated"] = "No"
End If
End Using
End Using

Related

How to quick update MySQL table through a loop using VB.net

My code for updating mysql table having more than 2000 rows through a loop using VB.net is working fine but too slow. Is there any way to update it faster ? Anybody please help. Thanks. My code is given below.
Dim mysqlconn = New MySqlConnection
mysqlconn.ConnectionString = "server=localhost;user id=root;password=1234;database=Share"
mysqlconn.Open()
Dim adapter As New MySqlDataAdapter("SELECT * FROM name_list;", mysqlconn)
Dim datatable As New DataTable()
adapter.Fill(datatable)
Dim cmd As New MySqlCommand
cmd.Connection = mysqlconn
Dim sql As String
Dim i as integer = 0
While i <= datatable.Rows.Count - 1
Dim sy As String = datatable.Rows(i).Item(3).ToString.Trim
sql = "UPDATE Name_list Set Numerology = '" & "N-" & variable1 & " S- " & variable2 & "',FSTLetter = '" & variable3 & "',Timing = '" & vriable4 & "',P_Numerology = '" & variable5 & "' WHERE Symbol = '" & sy & "'"
sy = ""
cmd.CommandText = sql
cmd.ExecuteNonQuery()
i = i + 1
End While
adapter.Fill(datatable)
DataGridView1.DataSource = datatable
DataGridView1.Refresh()
Don't name variables the same as class names (DataTable, datatable) vb.net is case insensitive so it confuses intellisense.
Database connections and commands need to closed and disposed.
Using blocks do this for you even if there is an error.
You can set the connection string by passing it directly to the constructor of the connection. Likewise, you can set the command text and the connection by passing to the constructor of the command.
Don't open the connection until right before it is used. In this case we don't need a DataAdapter but if you are using one it is not necessary to open the connection at all. The .Fill method of the DataAdapter will open and close the connection. However if the DataAdapter finds an open connection it will leave it open.
To avoid confusion, I created 2 data tables. I used a single connection but I opened and closed it each time it is used. It is not disposed until the last End Using.
The first command retrieves only the sy column. Replace Column4_Name with the actual column name. We don't want to pull down data we don't need so no Select *.
Always use parameters to avoid sql injection which can damage your database. You need to check your database for the types of the fields. I had to guess. Each parameters value is set except sy which changes on each iteration.
No need to close the connection after the last Select command since the final End Using will close and dispose.
After the connection is closed we update the user interface.
Private Sub OPCode(variable1 As String, variable2 As String, variable3 As String, variable4 As String, variable5 As String)
Dim dtBeforeUpdate As New DataTable()
Dim dtAfterUpdate As New DataTable()
Using mysqlconn = New MySqlConnection("server=localhost;user id=root;password=1234;database=Share")
Using cmd As New MySqlCommand("SELECT Column4_Name FROM name_list;", mysqlconn)
mysqlconn.Open()
dtBeforeUpdate.Load(cmd.ExecuteReader)
mysqlconn.Close()
End Using
Using cmd As New MySqlCommand($"UPDATE Name_list Set Numerology = #Numerologh, FSTLetter = #FST, Timing = #Timing, P_Numerology = #P_Numerology WHERE Symbol = #sy ", mysqlconn)
cmd.Parameters.Add("#Numerology", MySqlDbType.String).Value = $"N-{variable1} S- {variable2}"
cmd.Parameters.Add("#FST", MySqlDbType.String).Value = variable3
cmd.Parameters.Add("#Timing", MySqlDbType.String).Value = variable4
cmd.Parameters.Add("#P_Numerology", MySqlDbType.String).Value = variable5
cmd.Parameters.Add("#sy", MySqlDbType.String)
mysqlconn.Open()
For Each row As DataRow In dtBeforeUpdate.Rows
cmd.Parameters("#sy").Value = row(0).ToString.Trim
cmd.ExecuteNonQuery()
Next
mysqlconn.Close()
End Using
Using cmd As New MySqlCommand("Select * From Name_list;", mysqlconn)
mysqlconn.Open()
dtAfterUpdate.Load(cmd.ExecuteReader)
End Using
End Using
DataGridView1.DataSource = dtAfterUpdate
End Sub
Actually, I don't get it. It seems like you are updated the entire table with the same data. Do you expect the variable1, variable2 etc. to change somehow?
Don't know where your variable1, variable2, etc come from, but those look to be static, so your loop is somewhat pointless it would seem. You're updating every row in the loop to the exact same values (unless there's other code you're not showing), so just update the table without the loop:
Using con As New MySQLConnection
con.ConnectionString = "server=localhost;user id=root;password=1234;database=Share"
con.Open
Using cmd As New MySQLCommand
cmd.Connection = con
cmd.CommandText = "UPDATE Name_list Set Numerology = '" & "N-" & variable1 & " S- " & variable2 & "',FSTLetter = '" & variable3 & "',Timing = '" & vriable4 & "',P_Numerology = '" & variable5 & "'"
cmd.ExecuteNonQuery
End Using
End Using

Why is Visual Studio (VB) not reading my SQL connection string properly?

I am writing a small windows tool to search a few SQL databases. I was able to connect and search the first database without issues but I keep getting the following login error when I try to search the second database (Database 2):
'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Login failed for user '\azahir'
You will find that <Domain>\azahir is not even specified in my connection string or anywhere in my few lines of code.
Imports System.Data
Imports System.Data.SqlClient
Public Class Form1
Dim Conn As SqlConnection
Dim Conn2 As SqlConnection
Private Sub btSearch_Click(sender As Object, e As EventArgs) Handles btSearch.Click
Conn = New SqlConnection("Data Source = <SERVER>;Initial Catalog=<DATABASE>;Integrated Security=SSPI;User ID = <Domain> \ axzahir;Password=<Password>;")
Conn.Open()
Dim cmd2 As SqlCommand = Conn.CreateCommand
cmd2.CommandText = "select firstname, lastname
from systemuserbase where firstname like" + "'%" + TxFirstName.Text + "%'" +
" And lastname Like" + " '%" + TxLastname.Text + "%'"
Dim dir As SqlDataReader = cmd2.ExecuteReader()
If dir.HasRows Then
Dim dtClient As New DataTable
dtClient.Load(dir)
dtOutput.DataSource = dtClient
End If
dir.Close()
Conn.Close()
End Sub
....
Private Sub btnArgus_Click(sender As Object, e As EventArgs) Handles btnArgus.Click
Conn2 = New SqlConnection("Data Source = <SERVER2>;Initial Catalog=<DATABASE 2>;Integrated Security=SSPI;User ID = <DOMAIN> \ axzahir;Password=<PASSWORD>;")
Conn2.Open()
Dim cmd3 As SqlCommand = Conn2.CreateCommand
cmd3.CommandText = "select userID, Fullname
from Users where FullName like" + "'%" + TxFirstName.Text + "%'" +
" And Fullname Like" + " '%" + TxLastname.Text + "%'"
Dim dir3 As SqlDataReader = cmd3.ExecuteReader()
If dir3.HasRows Then
Dim dtClient As New DataTable
dtClient.Load(dir3)
dtOutput.DataSource = dtClient
End If
dir3.Close()
Conn2.Close()
End Sub
End Class
I have verified that my domain/username + password works for database 2. I am stumped as to why Visual Studio thinks my user is '\azahir' instead of the specified '\axzahir'. Any thoughts on how this can be fixed?
Thank you,
Asif
That's not how integrated security works. When using integrated security, there is no way to specify a specific username or the password. Instead, you get the user authorization for whatever user account runs your program. The entire connection string looks like this, with no specific user information:
Data Source = <SERVER>;Initial Catalog=<DATABASE>;Integrated Security=SSPI;
If you want to specify a username and password, you must use SQL authentication. If you want to access the database as a specific domain account, you use integrated security, but you have to run your app as that user. There is no way to specify Active Directory credentials in a connection string and get that user's database access.
While I'm here, let me show you a better pattern for your database connection. (One that's not crazy vulnerable to sql injection! and will remember to close the connection even if an exception is thrown.)
Assuming a valid connection string:
Private ConnString As String = "connection string here"
Private Sub btSearch_Click(sender As Object, e As EventArgs) Handles btSearch.Click
Dim SQL As String = _
"SELECT firstname, lastname " &
"FROM systemuserbase " &
"WHERE firstname like '%' + #FirstName + '%' AND lastname Like '%' + #LastName + '%';"
Using Conn As New SqlConnection(ConnString), _
cmd As New SqlCommand(SQL, Conn)
'Use actual database column types and lengths here
cmd.Parameters.Add("#FirstName", SqlDbType.NVarChar, 20).Value = TxFirstName.Text
cmd.Parameters.Add("#LastName", SqlDbType.NVarChar, 20).Value = TxLastName.Text
Conn.Open()
Using dir As SqlDataReader = cmd2.ExecuteReader()
dtOutput.DataSource = dir
dir.Close()
End Using
End Using
End Sub
Private Sub btnArgus_Click(sender As Object, e As EventArgs) Handles btnArgus.Click
Dim SQL As String = _
"SELECT userID, Fullname " &
"FROM Users " &
"WHERE FullName like '%' + #FirstName + '%' AND Fullname Like '%' + #Lastname + '%';"
'Note I can use the same variable names.
' These are scoped to the method, not the class.
' Different scope, different variables, even though the names are the same
Using Conn AS New SqlConnection(ConnString), _
cmd As New SqlCommand(SQL, Conn)
'Use actual database column types and lengths here
cmd.Parameters.Add("#FirstName", SqlDbType.NVarChar, 20).Value = TxFirstName.Text
cmd.Parameters.Add("#LastName", SqlDbType.NVarChar, 20).Value = TxLastName.Text
Conn.Open()
Using dir As SqlDataReader = cmd.ExecuteReader()
dtOutput.DataSource = dir
dir.Close()
End Using
End Using
End Sub

ExecuteReader: CommandText property has not been initialized when trying to make a register form for my database

hello guys im trying to script a register form for my database and i came with this code >> so can anyone help ?
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim cn As New SqlConnection
Dim cmd As New SqlCommand
Dim dr As SqlDataReader
cn.ConnectionString = "Server=localhost;Database=test;Uid=sa;Pwd=fadyjoseph21"
cmd.Connection = cn
cmd.CommandText = "INSERT INTO test2(Username,Password) VALUES('" & TextBox1.Text & "','" & TextBox2.Text & "')"
cn.Open()
dr = cmd.ExecuteReader
If dr.HasRows Then
MsgBox("You're already registered")
Else
MsgBox("Already registered")
End If
End Sub
Edit your Code in this way..
cmd.CommandText = "INSERT INTO User_Data(Username,Password) VALUES('" & TextBox1.Text & "' , '" & TextBox2.Text & "')"
cn.Open()
cmd.ExecuteNonQuery()
cn.Close()
Insert will not retrieve any records it's a SELECT statement you want to use .I'll suggest you use stored procedures instead to avoid Sql-Injections.
ExecuteReader it's for "SELECT" queries, that helps to fill a DataTable. In this case you execute command before cmd.commandText is defined.
You should have define cmd.commandText before and use ExecuteNonQuery after, like this.
Dim cn As New SqlConnection
Dim cmd As New SqlCommand
cn.ConnectionString = "Server=localhost;Database=test;Uid=sa;Pwd=fadyjoseph21"
cmd.Connection = cn
cn.Open()
cmd.CommandText = "INSERT INTO User_Data(Username,Password) VALUES('" & TextBox1.Text & "','" & TextBox2.Text & "')"
cmd.ExecuteNonQuery()
cn.Close()
cmd.CommandText should be assigned stored proc name or actual raw SQL statement before calling cmd.ExecuteReader
Update:
Change code as follows
....
cmd.Connection = cn
cmd.CommandText = "select * from TblToRead where <filter>" ''This is select query statement missing from your code
cn.Open()
dr = cmd.ExecuteReader ....
where <filter> will be something like username = "' & Request.form("username') & '" '
The error itself is happening because you're trying to execute a query before you define that query:
dr = cmd.ExecuteReader
'...
cmd.CommandText = "INSERT INTO User_Data(Username,Password) VALUES('" & TextBox1.Text & "' and '" & TextBox2.Text & "')"
Naturally, that doesn't make sense. You have to tell the computer what code to execute before it can execute that code:
cmd.CommandText = "INSERT INTO User_Data(Username,Password) VALUES('" & TextBox1.Text & "' and '" & TextBox2.Text & "')"
'...
dr = cmd.ExecuteReader
However, that's not your only issue...
You're also trying to execute a DataReader, but your SQL command doesn't return data. It's an INSERT command, not a SELECT command. So you just need to execute it directly:
cmd.CommandText = "INSERT INTO User_Data(Username,Password) VALUES('" & TextBox1.Text & "' and '" & TextBox2.Text & "')"
cmd.ExecuteNonQuery
One value you can read from an INSERT command is the number of rows affected. Something like this:
cmd.CommandText = "INSERT INTO User_Data(Username,Password) VALUES('" & TextBox1.Text & "' and '" & TextBox2.Text & "')"
Dim affectedRows as Int32 = cmd.ExecuteNonQuery
At this point affectedRows will contain the number of rows which the query inserted successfully. So if it's 0 then something went wrong:
If affectedRows < 1 Then
'No rows were inserted, alert the user maybe?
End If
Additionally, and this is important, your code is wide open to SQL injection. Don't directly execute user input as code in your database. Instead, pass it as a parameter value to a pre-defined query. Basically, treat user input as values instead of as executable code. Something like this:
cmd.CommandText = "INSERT INTO User_Data(Username,Password) VALUES(#Username,#Password)"
cmd.Parameters.Add("#Username", SqlDbType.NVarChar, 50).Value = TextBox1.Text
cmd.Parameters.Add("#Password", SqlDbType.NVarChar, 50).Value = TextBox2.Text
(Note: I guessed on the column types and column sizes. Adjust as necessary for your table definition.)
Also, please don't store user passwords as plain text. That's grossly irresponsible to your users and risks exposing their private data (even private data on other sites you don't control, if they re-use passwords). User passwords should be obscured with a 1-way hash and should never be retrievable, not even by you as the system owner.
You're attempting to change the CommandText after you're executing your query.
Try this:
Private cn = New SqlConnection("Server=localhost;Database=test;UID=sa;PWD=secret")
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim cmd As New SqlCommand
cmd.CommandText = "select * from table1" ' your sql query selecting data goes here
Dim dr As SqlDataReader
cmd.Connection = cn
cn.Open()
dr = cmd.ExecuteReader
If dr.HasRows = 0 Then
InsertNewData(TextBox1.Text, TextBox2.Text)
Else
MsgBox("Already registered")
End If
End Sub
Private Sub InsertNewData(ByVal username As String, ByVal password As String)
Dim sql = "INSERT INTO User_Data(Username,Password) VALUES(#Username, #Password)"
Dim args As New List(Of SqlParameter)
args.Add(New SqlParameter("#Username", username))
args.Add(New SqlParameter("#Password", password))
Dim cmd As New SqlCommand(sql, cn)
cmd.Parameters.AddRange(args.ToArray())
If Not cn.ConnectionState.Open Then
cn.Open()
End If
cmd.ExecuteNonQuery()
cn.Close()
End Sub
This code refers the INSERT command to another procedure where you can create a new SqlCommand to do it.
I've also updated your SQL query here to use SqlParameters which is much more secure than adding the values into the string directly. See SQL Injection.
The InsertNewData method builds the SQL Command with an array of SQLParameters, ensures that the connection is open and executes the insert command.
Hope this helps!

Visual basic - Incrementing the score

Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim READER As MySqlDataReader
Dim Query As String
Dim connection As MySqlConnection
Dim COMMAND As MySqlCommand
Dim item As Object
Try
item = InputBox("What is the item?", "InputBox Test", "Type the item here.")
If item = "shoe" Then
Dim connStr As String = ""
Dim connection As New MySqlConnection(connStr)
connection.Open()
Query = "select * from table where username= '" & Login.txtusername.Text & " '"
COMMAND = New MySqlCommand(Query, connection)
READER = COMMAND.ExecuteReader
If (READER.Read() = True) Then
Query = "UPDATE table set noOfItems = noOfItems+1, week1 = 'found' where username= '" & Login.txtusername.Text & "'"
Dim noOfItems As Integer
Dim username As String
noOfItems = READER("noOfItems") + 1
username = READER("username")
MessageBox.Show(username & "- The number of items you now have is: " & noOfGeocaches)
End If
Else
MsgBox("Unlucky, Incorrect item. Please see hints. Your score still remains the same")
End If
Catch ex As Exception
MessageBox.Show("Error")
End Try
I finally got the message box to display! but now my code does not increment in the database, can anybody help me please :D
Thanks in advance
After fixing your typos (space after the login textbox and name of the field retrieved) you are still missing to execute the sql text that updates the database.
Your code could be simplified understanding that an UPDATE query has no effect if the WHERE condition doesn't find anything to update. Moreover keeping an MySqlDataReader open while you try to execute a MySqlCommand will trigger an error in MySql NET connector. (Not possible to use a connection in use by a datareader). We could try to execute both statements in a single call to ExecuteReader separating each command with a semicolon and, of course, using a parameter and not a string concatenation
' Prepare the string for both commands to execute
Query = "UPDATE table set noOfItems = noOfItems+1, " & _
"week1 = 'found' where username= #name; " & _
"SELECT noOfItems FROM table WHERE username = #name"
' You already know the username, don't you?
Dim username = Login.txtusername.Text
' Create the connection and the command inside a using block to
' facilitate closing and disposing of these objects.. exceptions included
Using connection = New MySqlConnection(connStr)
Using COMMAND = New MySqlCommand(Query, connection)
connection.Open()
' Set the parameter value required by both commands.
COMMAND.Parameters.Add("#name", MySqlDbType.VarChar).Value = username
' Again create the reader in a using block
Using READER = COMMAND.ExecuteReader
If READER.Read() Then
Dim noOfItems As Integer
noOfItems = READER("noOfItems")
MessageBox.Show(username & "- The number of items you now have is: " & noOfItems )
End If
End Using
End Using
End Using

Storing ID from SQL result

Im running the following code to tell if a user excists on a database - standard stuff. Obviously once the code is run a boolean true or false will be returned if there is a result. If a result is found i want to store the ID of the said result. Can anyone tell me how'd id go about doing this?
code:
Username = txtUserName.Text
Password = txtPassword.Text
dbConnInfo = "PROVIDER=Microsoft.Jet.OLEDB.4.0; Data Source = C:\Users\Dave\Documents\techs.mdb"
con.ConnectionString = dbConnInfo
con.Open()
Sql = "SELECT * FROM techs WHERE userName = '" & Username & "' AND '" & Password & "'"
LoginCommand = New OleDb.OleDbCommand(Sql, con)
CheckResults = LoginCommand.ExecuteReader
RowsFound = CheckResults.HasRows
con.Close()
If RowsFound = True Then
MsgBox("Details found")
TechScreen.Show()
Else
MsgBox("Incorrect details")
End If
There are a lot of problems with the code snippet you posted. Hopefully, I can help you correct these problems.
In order to load the ID of the result you'll want to use SqlCommand.ExecuteScalar() as this is optimized to pull back one result from Sql.
As to what is wrong with your code, you're wide open to Sql Injection attacks and you should be using Parametrized Queries as shown in my sample below.
Public Function AddProductCategory( _
ByVal newName As String, ByVal connString As String) As Integer
Dim newProdID As Int32 = 0
Dim sql As String = _
"INSERT INTO Production.ProductCategory (Name) VALUES (#Name); " _
& "SELECT CAST(scope_identity() AS int);"
Using conn As New SqlConnection(connString)
Dim cmd As New SqlCommand(sql, conn)
cmd.Parameters.Add("#Name", SqlDbType.VarChar)
cmd.Parameters("#Name").Value = newName
Try
conn.Open()
newProdID = Convert.ToInt32(cmd.ExecuteScalar())
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Using
Return newProdID
End Function
Source: MSDN