I am using ASP Classic and SQL Server 2000 to create dynamic websites.
I am a bit confused about when to use a recordset object and when to use a command object when querying the database.
I was told that if the stored procedure would be returning records from a SELCT statement then I should use a recordset, however if I am up updating or inserting then I should use a command object and pass all data as parameters to the stored procedure.
When using a recordset I often pass any required data like so:
rs.Source = "spTest " & id
I alway validate the data that I am passing to make sure it is what I am expecting and cast it to its correct type.
I have since been told however that the above method leaves my code open to SQL Injection 开发者_高级运维attacks and that I should always use a command object.
Is this correct?
Thanks
Yes, that's right.
Imagine someone passing the string: '0; delete * from users;'
You query would then be:
spTest 0; delete * from users;
If you're lucky you won't have a users table. Personally, I would use the command object all the time for consistency. You can get everything you need from it.
Here is a quick example of how you might do it with the command object:
Dim oStoredProc : Set oStoredProc = Server.CreateObject("ADODB.Command")
With oStoredProc
.ActiveConnection = oDBConnection
.CommandType = adCmdStoredProc
.CommandText = "up_procname"
.Parameters.Append(.CreateParameter("@Param1", ADODB.adInteger, ADODB.adParamInput, 22, 11))
.Parameters.Append(.CreateParameter("@Param2", ADODB.adInteger, ADODB.adParamOutput, 22, 12)
Call .Execute()
myVal = .Parameters("@Param2")
End With
Set oStoredProc = Nothing
What you were told is correct indeed : you should always use commande objects to prevent SQL Injection. Using parameterized queries, you leave all the security and validation of parameters to the ADO layer (though you should still do your own proper validation), and you may even get some performance improvement (these parameterized queries are cached by SQL Server)
When you execute a command you have two options : either the SQL you execute returns rows (A SELECT Statement, or some stored procedures), then you have to use a recordset to store these rows, either it doesn't (UPDATES, DELETES, other procedures), then you juste execute the command and do not worry about recordsets.
Edit : just to make sure everything is clear for you, I used James Wiseman's code above and adapted it to your example :
Dim oStoredProc : Set oStoredProc = Server.CreateObject("ADODB.Command")
With oStoredProc
.ActiveConnection = oDBConnection
.CommandType = adCmdStoredProc
.CommandText = "spTest ?"
.Parameters.Append(.CreateParameter("id", ADODB.adInteger, ADODB.adParamInput, id, 11))
Dim rs : Set rs = .Execute()
End With
Set oStoredProc = Nothing
Didn't test it, but should be ok :-)
Last but not least : even though you're pretty well protected now, don't forget that if you're using dynamic SQL inside your stored procedure you may still have an SQL Injection security hole (as soon as you're concatenating strings to create SQL you may be vulnerable I would say) !
精彩评论