VB.NET SQL limit submission attempts - asp.net

I have a submission page that I need to limit the number of attempts that a user can try in a specific time period.
There is a stored procedure that is called that checks for certain data in database1 and also logs the IP address and the date/time the form was submitted into database2.
All I need to do is check how many attempts have been logged by that IP address within a 30 minute time period and restrict further submission attempts if that number is over 5.
Here is my VB code:
Protected Sub btn_Cont_Click(sender As Object, e As EventArgs) Handles btn_Cont.Click
Dim StudentIDLast4 As Integer = Val(textSSN.Text)
Dim StudentIDInst As String = textSID.Text.ToUpper
Dim DateOfBirth As String = textDOB.Text
Dim IPaddress As String = Request.UserHostAddress()
Dim sqlConnection1 As New SqlConnection("Data Source=(localdb)\v11.0;Initial Catalog=tempdb;Integrated Security=True")
Dim cmd As New SqlCommand
Dim returnValue As String
Dim returnCount As Integer
cmd.CommandText = "proc_ReverseTransferConsent_Find_Match"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#StudentIDLast4", StudentIDLast4)
cmd.Parameters.AddWithValue("#StudentIDInst", StudentIDInst)
cmd.Parameters.AddWithValue("#DateOfBirth", DateOfBirth)
cmd.Parameters.AddWithValue("#IPaddress", IPaddress)
cmd.Connection = sqlConnection1
Dim sqlConnection2 As New SqlConnection("Data Source=(localdb)\v11.0;Initial Catalog=tempdb;Integrated Security=True")
Dim attempts As String
Dim comm As New SqlCommand("SELECT [Count] = COUNT(*) FROM ReverseTransferConsent_Attempt WHERE IPaddress = #IPaddress AND CreatedDate > DATEADD(MINUTE, -30, GETDATE())")
Dim ap As New SqlDataAdapter(comm.CommandText, sqlConnection1)
Dim ds As New DataSet()
comm.Parameters.AddWithValue("#IPaddress", IPaddress)
If Page.IsValid Then
sqlConnection2.Open()
ap.Fill(ds)
attempts = ds.Tables(0).Rows.Count.ToString()
sqlConnection2.Close()
sqlConnection1.Open()
returnValue = Convert.ToString(cmd.ExecuteScalar())
sqlConnection1.Close()
returnCount = returnValue.Length
If attempts <= 5 Then
If returnCount > 4 Then
Response.Redirect("RTAgreement.aspx?rVal=" + returnValue)
Else
Label2.Text = StudentIDInst
End If
ElseIf attempts > 5 Then
Label2.Text = "Only 5 submission attempts allowed per 30 minutes"
End If
End If
End Sub
It's giving me the error:
An exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll but was not handled in user code
Additional information: Must declare the scalar variable "#IPaddress".
I declared the variable using AddWithValue. Is that not correct?

The problem is that you instantiate your SqlDataAdapter using command text only (passing the query but not parameters) so it doesn't have the parameter passed:
Dim ap As New SqlDataAdapter(comm.CommandText, sqlConnection1)
you should use the command instead and instantiate your command passing the connection as well:
Dim comm As New SqlCommand("SELECT [Count] = COUNT(*) FROM ReverseTransferConsent_Attempt WHERE IPaddress = #IPaddress AND CreatedDate > DATEADD(MINUTE, -30, GETDATE())", sqlConnection1)
Dim ap As New SqlDataAdapter(comm)

You might have an instance of SQL Server will be case sensitive. Can you check how IPAddress parameter is defined in proc_ReverseTransferConsent_Find_Match stored procedure?

Just for reference for anyone else who may have a similar issue or might be trying to accomplish the same task that finds this thread.
This is what I had to do to get it to count properly and not return 1 every time:
Dim sqlConnection2 As New SqlConnection("Data Source=(localdb)\v11.0;Initial Catalog=tempdb;Integrated Security=True")
Dim attempts As String = ""
Dim comm As New SqlCommand("SELECT [Count] = COUNT(*) FROM ReverseTransferConsent_Attempt WHERE IPaddress = #IPaddress AND CreatedDate > DATEADD(MINUTE, -30, GETDATE())", sqlConnection1)
comm.Parameters.AddWithValue("#IPaddress", IPaddress)
comm.Connection = sqlConnection2
If Page.IsValid Then
sqlConnection2.Open()
attempts = Convert.ToString(comm.ExecuteScalar())
sqlConnection2.Close()

Related

getting data from database asp.net

i am trying to get data from ms access database using this code but i can not this is my code is this correct
Dim query As String = "SELECT [data] FROM tabless WHERE user = '" & user.Text & "'"
Using connection As New OleDbConnection(connectionString)
Dim cmd As New OleDbCommand(query)
Dim adapter As OleDbDataAdapter = New OleDbDataAdapter(query, connection)
Dim com As New OleDbCommand(query, connection)
connection.Open()
'on the line below I get an error: connection property has not been initialized
Dim reader As OleDbDataReader = cmd.ExecuteReader()
While reader.Read()
Label1.Text = (reader(0).ToString())
End While
reader.Close()
End Using
Database
|data|
asl
trying to get data from database and trying to show it in a label is this possible
You never associated cmd with the connection, and you never use com or adapter. This is the sort of thing you can figure out by stepping through your code line by line and inspecting the state of it.
Dim query As String = "SELECT [data] FROM tabless WHERE user = '" & user.Text & "'"
Using connection As New OleDbConnection(connectionString)
Dim cmd As New OleDbCommand(query, connection)
connection.Open()
Dim reader As OleDbDataReader = cmd.ExecuteReader()
While reader.Read()
Label1.Text = (reader(0).ToString())
End While
reader.Close()
End Using
Also, your code is vulnerable to a SQL Injection Attack. You should not be concatenating strings together to form your queries. You should instead use parameterized queries.

Multiple user accessing Webservice simultaneously

We have a WebMethod created in an ASP.NET 2.0 Web Service (VB), which is accessed throughout the application very frequently. The WebMethod gets the query as a parameter and returns the DataSet. It works fine when the number of users is 1 or 2. If ~30 users are using the system simultaneously, the WebMethod returns the DataSet of a different query. We have tried the synclock (lock in C#) option, but it does not work.
Public Function ExecuteQry(ByVal StrText As String) As DataSet
Dim AdoDs As New DataSet()
Dim SqlDp As New SqlDataAdapter
Dim SqlCmd As New SqlCommand
Dim SqlParam As New SqlParameter
Try
SyncLock AdoDs
MakeConnect()
With SqlCmd
.Connection = SqlCon
.CommandText = "rExecuteQry"
.CommandType = CommandType.StoredProcedure
End With
SqlParam = SqlCmd.Parameters.AddWithValue("#strText", Trim(StrText))
SqlDp.SelectCommand = SqlCmd
SqlDp.Fill(AdoDs)
DisposeConnect()
Return AdoDs
End SyncLock
Catch ex As SqlException
DisposeConnect()
Debug.Write(ex.Message)
Finally
SqlCmd = Nothing
SqlParam = Nothing
End Try
End Function
Below is the stored procedure:
ALTER PROCEDURE [dbo].[rExecuteQry]
#strText Varchar (max)
as
Exec( #StrText)

ASP.net dataset

da = New SqlDataAdapter("select * from revision_cycle_documenttype_mapping where project_id=" & Session("project_id"), con)
cb = New SqlCommandBuilder(da)
ds = New DataSet
da.Fill(ds, "revision_cycle_documenttype_mapping") <<--
mapping_count = ds.Tables("revision_cycle_documenttype_mapping").Rows.Count
Response.Write(mapping_count)
I am getting an error "Incorrect syntax near '=' ".
I have shown on which portion it's throwing error i.e da.fill.
Can you please help me?
EDIT
If it throws error on da.Fill then try to see the resulting SQL code first. Your project_id may be empty.
Edit
This is a possible solution
Dim projectId As Integer
If Session("project_id") IsNot Nothing AndAlso IsNumeric(Session("project_id")) Then
projectId = Session("project_id")
da = New SqlDataAdapter("select * from revision_cycle_documenttype_mapping where project_id=" & projectId, con)
cb = New SqlCommandBuilder(da)
ds = New DataSet
da.Fill(ds, "revision_cycle_documenttype_mapping") <<--
mapping_count = ds.Tables("revision_cycle_documenttype_mapping").Rows.Count
Response.Write(mapping_count)
End If
I think your session Session("project_id") is empty, and this is not the best way to add a parameter in ur sql statement. your code here is vulnerable to sql injections.
you should first check if your session is empty and then you should add parameters by declaring a sqlcommand and assign parameters to it:
dim project_id as integer = 0
If Session("project_id") IsNot Nothing AndAlso IsNumeric(Session("project_id")) Then
project_id = Session("project_id")
end if
dim cmd as new sqlcommand
cmd.parameters.add("#project_id",project_id)
the rest of your code would stay the same
Use Parameters and check the null.
Dim projectid=0
If Not IsNothing(Session("project_id")) Then
projectid=DirectCast(Session("project_id"),Integer)
End If
Dim sql="select * from revision_cycle_documenttype_mapping where project_id=#project_id"
dim cmd as new SqlCommand(sql,con)
cmd.Parameters.AddWithValue("#project_id",projectid)
da = New SqlDataAdapter=(cmd)
cb = New SqlCommandBuilder(da)
ds = New DataSet
da.Fill(ds, "revision_cycle_documenttype_mapping")

Help with asp login SQL

I have a form which goes to the following login script when it is submitted.
<%
Dim myConnection As System.Data.SqlClient.SqlConnection
Dim myCommand As System.Data.SqlClient.SqlCommand
Dim requestName As String
Dim requestPass As String
requestName = Request.Form("userName")
requestPass = Request.Form("userPass")
Dim queryString As String = "SELECT COUNT(*) AS Num_Of_User FROM tblusers WHERE username='" & requestName & "' AND password='" & requestPass & "'"
myConnection = New System.Data.SqlClient.SqlConnection("Data Source=(local);InitialCatalog=dbtest;Integrated Security=True")
myCommand = New System.Data.SqlClient.SqlCommand(queryString, myConnection)
myConnection.Open()
Dim reader As System.Data.SqlClient.SqlDataReader = myCommand.ExecuteReader()
%>
Now in theory, I should be able to get that Num_Of_User from the SQL Query and if it equals 1 than the login was successful. Is this the correct way? And how can I get the value that the SQL returns?
You are wide open to SQL injection using that code.
See happens if you enter the username as ' OR 2>1--
You need to change the to use a parametrized query.
Dim queryString As String = "SELECT COUNT(*) AS Num_Of_User FROM tblusers WHERE username=#username AND password=#password"
myConnection = New System.Data.SqlClient.SqlConnection("Data Source=(local);InitialCatalog=dbtest;Integrated Security=True")
myCommand = New System.Data.SqlClient.SqlCommand(queryString, myConnection)
myCommand.Parameters.AddWithValue("#username", requestName)
myCommand.Parameters.AddWithValue("#password", requestPass)
Also you are not handling any exceptions that might be thrown, nor disposing your objects.
Your code should look more like the following.
Dim numUsers as Integer
Using myConnection as New System.Data.SqlClient.SqlConnection("Data Source=(local);InitialCatalog=dbtest;Integrated Security=True")
Dim queryString As String = "SELECT COUNT(*) AS Num_Of_User FROM tblusers WHERE username=#username AND password=#password"
Using myCommand as New System.Data.SqlClient.SqlCommand(queryString, myConnection)
myConnection.Open
myCommand.Parameters.AddWithValue("#username", requestName)
myCommand.Parameters.AddWithValue("#password", requestPass)
numUsers = myCommand.ExecuteScalar()
End Using
End Using
The above code will make sure your objects are disposed, but won't handle any exceptions that might be thrown.
Try myCommand.ExecuteScalar(), which returns the value from the first column in the first row of the resultset - exactly the value you're after here.
Also, check into the ASP.Net 'built in' authentication methods - this might save you some effort.

oRecordset in ASP.NET mySQL

I have this mySQL code that connects to my server. It connects just fine:
Dim MyConString As String = "DRIVER={MySQL ODBC 3.51 Driver};" & _
"SERVER=example.com;" & _
"DATABASE=xxx;" & _
"UID=xxx;" & _
"PASSWORD=xxx;" & _
"OPTION=3;"
Dim conn As OdbcConnection = New OdbcConnection(MyConString)
conn.Open()
Dim MyCommand As New OdbcCommand
MyCommand.Connection = conn
MyCommand.CommandText = "select * from userinfo WHERE emailAddress = '" & theUN & "'""
MyCommand.ExecuteNonQuery()
conn.Close()
However, i have an old Classic ASP page that uses "oRecordset" to get the data from the mySQL server:
Set oConnection = Server.CreateObject("ADODB.Connection")
Set oRecordset = Server.CreateObject("ADODB.Recordset")
oConnection.Open "DRIVER={MySQL ODBC 3.51 Driver}; SERVER=example.com; PORT=3306; DATABASE=xxx; USER=xxx; PASSWORD=xxx; OPTION=3;"
sqltemp = "select * from userinfo WHERE emailAddress = '" & theUN & "'"
oRecordset.Open sqltemp, oConnection,3,3
And i can use oRecordset as follows:
if oRecordset.EOF then....
or
strValue = oRecordset("Table_Name").value
or
oRecordset("Table_Name").value = "New Value"
oRecordset.update
etc...
However, for the life of me, i can not find any .net code that is similar to that of my Classic ASP page!!!!!
Any help would be great! :o)
David
This is what you have to do:
instead of MyCommand.ExecuteNonQuery you should use MyCommand.ExecuteQuery and assign it to DataReader.
Check out this sample:
Dim myConnection As SqlConnection
Dim myCommand As SqlCommand
Dim dr As New SqlDataReader()
'declaring the objects
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)_
Handles MyBase.Load
myConnection = New SqlConnection("server=localhost;uid=sa;pwd=;database=pubs")
'establishing connection. you need to provide password for sql server
Try
myConnection.Open()
'opening the connection
myCommand = New SqlCommand("Select * from discounts", myConnection)
'executing the command and assigning it to connection
dr = myCommand.ExecuteReader()
While dr.Read()
'reading from the datareader
MessageBox.Show("discounttype" & dr(0).ToString())
MessageBox.Show("stor_id" & dr(1).ToString())
MessageBox.Show("lowqty" & dr(2).ToString())
MessageBox.Show("highqty" & dr(3).ToString())
MessageBox.Show("discount" & dr(4).ToString())
'displaying the data from the table
End While
dr.Close()
myConnection.Close()
Catch e As Exception
End Try
HTH
Dim conn As OdbcConnection = New OdbcConnection("DRIVER={MySQL ODBC 3.51 Driver}; SERVER=xxx.com; DATABASE=xxx; UID=xxx; PASSWORD=xxx; OPTION=3;")
conn.Open()
Dim MyCommand As New OdbcCommand
MyCommand.Connection = conn
MyCommand.CommandText = "SELECT * FROM userinfo"
Dim rst = MyCommand.ExecuteReader()
While rst.Read()
response.write(rst("userID").ToString())
End While
conn.Close()
Dim email As String = "anyone#anywhere.com"
Dim stringValue As String
Using conn As OdbcConnection = New OdbcConnection(MyConString)
conn.Open()
Dim sql = "Select ... From userInfo Where emailAddress = #Email"
Using cmd As OdbcCommand = New OdbcCommand(sql, conn)
cmd.Parameters.AddWithValue("#Email", email)
Dim reader As OdbcDataReader = cmd.ExecuteReader()
While reader.Read()
stringValue = reader.GetString(0)
End While
End Using
conn.Close()
End Using
'To do an Update
Using conn As OdbcConnection = New OdbcConnection(MyConString)
conn.Open()
Dim sql As String = "Update userInfo Set Column = #Value Where PK = #PK"
Using cmd As OdbcCommand = New OdbcCommand(sql, conn)
cmd.Parameters.AddWithValue("#Email", email)
cmd.ExecuteNonQuery()
End Using
End Using
'To do an Insert
Using conn As OdbcConnection = New OdbcConnection(MyConString)
conn.Open()
Dim sql As String = "Insert userInfo(Col1,Col2,...) Values(#Value1,#Value2...)"
Using cmd As OdbcCommand = New OdbcCommand(sql, conn)
cmd.Parameters.AddWithValue("#Col1", value1)
cmd.Parameters.AddWithValue("#Col2", value2)
...
cmd.ExecuteNonQuery()
End Using
End Using
First, even in ASP Classic, it is an absolutely horrid approach to concatenate a value directly into a SQL statement. This is how SQL Injection vulnerabilities happen. You should always sanitize values that get concatenated into SQL statements. In .NET, you can use parametrized queries where you replace the values that go into your query with a variable that begins with an # sign. You then add a parameter to the command object and set your value that way. The Command object will sanitize the value for you.
ADDITION
You mentioned in a comment that your ASP Classic code is shorter. In fact, the .NET code is shorter because there are a host of things happening that you do not see and have not implemented in your ASP Classic code. I already mentioned one which is sanitizing the inputs. Another is logging. Out of the box, if an exception is thrown, it will log it in the Event Log with a call stack. To even get a call stack in ASP Classic is a chore much less any sort of decent logging. You would need to set On Error Resume Next and check for err.number <> 0 after each line. In addition, without On Error Resume Next, if an error is thrown, you have no guarantee that the connection will be closed. It should be closed, but the only way to know for sure is to use On Error Resume Next and try to close it.
Generally, I encapsulate all of my data access code into a set of methods so that I can simply pass the SQL statement and the parameter values and ensure that it is called properly each time. (This holds true for ASP Classic too).

Resources