C# 如何在vb.net中不使用参数使sql字符串安全
我正在从事一个用vb.net编写的项目,该项目有一个sql InInInjection问题,我几乎通过使用C# 如何在vb.net中不使用参数使sql字符串安全,c#,asp.net,.net,vb.net,sql-injection,C#,Asp.net,.net,Vb.net,Sql Injection,我正在从事一个用vb.net编写的项目,该项目有一个sql InInInjection问题,我几乎通过使用参数解决了所有注入问题,有一种情况是sql字符串被构建,然后被加密并传递到视图状态,然后它将从视图状态中检索和解密以运行,显然,在这种情况下不能使用params,而且重构到不在viewState中传递sql也是不可能的,唯一的选择是在尽可能多地构建sql语句时避免注入,或者使用参数然后获取生成的sql语句并将其传递到视图状态 参数值由字符串和数字混合而成 比如说 sSQL = sSQL &
参数解决了所有注入问题,有一种情况是sql字符串被构建,然后被加密并传递到视图状态
,然后它将从视图状态
中检索和解密以运行,显然,在这种情况下不能使用params,而且重构到不在viewState
中传递sql也是不可能的,唯一的选择是在尽可能多地构建sql语句时避免注入,或者使用参数然后获取生成的sql语句并将其传递到视图状态
参数值由字符串和数字混合而成
比如说
sSQL = sSQL & " WHERE Name LIKE '" & lstBrowse.SelectedItem.Value & "%'"
sSQL = sSQL & " WHERE State ='" & lstBrowse.SelectedItem.Value & "'"
sSQL = sSQL & " WHERE OrganizationID=" & lstBrowse.SelectedItem.Value
如果不使用参数,我如何做到这一点?我应该考虑和避免什么? OK,我认为问题是假设你不能有“可选”的参数,或者你必须提前设置它们。(你不知道)
您可以列出以下内容:
dim strWhere as string
strWhere = "(State = @State)
cmdSQL.Parmaters.Add("@State",SqlDbType.NVarchar).Value = lstBrowse.SelectedItem.Value
现在,我可以在两个strWhere中“动态”添加更多条件,并且随着时间的推移,可以在cmdSQL.parmaters集合中添加parmaters
现在,让我们假设您在某个复杂的网格页面上,用户选择了一些内容,现在您需要将该语句传递给另一个表单
Well, it gets a wee bit messy to have:
Keep track of some field names
Keep track of some conditions (=, like, etc.)
Keep track of the parameters
但您可以很肯定地将参数列表和一些与该参数匹配的sql“串”在一起。因此,不需要用现有的参数对sql进行硬编码
现在,另一个问题是,您建议不仅要构建一些动态sql,而且还需要在会话中传递它(或者您需要这种能力)
好的,我只需要构建一个非常短的代码“束”,将上面的所有代码放到一个非常短且简单的类中。然后把这门课推到课堂上
因此,将这一小段代码放入项目中的一个标准代码模块中
公共类SqlParms
Public cmdSQL As New SqlCommand("", GetCon)
Public Where As String
Private m_SQL As String
Public Sub Add(FieldName As String, Cond As String, FieldValue As Object, Datatype As SqlDbType)
Dim mycond As String
Dim prex As String = "", sufx As String = ""
If Left(Cond, 1) = "%" Then prex = "'%' + "
If Right(Cond, 1) = "%" Then sufx = " + '%'"
mycond = Replace(Cond, "%", "")
If Where <> "" Then Where += " AND "
Where += "(" & FieldName & " " & mycond & " " & prex & "@" & FieldName & sufx & ")"
cmdSQL.Parameters.Add("@" & FieldName, Datatype).Value = FieldValue
End Sub
Public Property SQL As String
Get
Return m_SQL
End Get
Set(value As String)
m_SQL = value & " WHERE " & Where
cmdSQL.CommandText = m_SQL
End Set
End Property
End Class
现在,请注意,一旦我们将会话指向那个类?然后我可以在当前代码位中添加/修改,而不必将MyParm导入/保存/推回—这是一个对象,现在它正在会话中
因此,让我们添加您的条件
MyParms.Add("State", "=", lstBrowse.SelectedItem.Value, SqlDbType.NVarChar)
好的,以上内容不仅被添加了,而且在我们的课程中也被添加了
好的,让我们假设我们有两个条件,第二个是ContactID(数据库中的一个PK值,因此是一个整数数据类型)。
好的,我们现在开始:
MyParms.Add("OrganziationID", "=", lstBrowse.SelectedItem.Value, SqlDbType.Int)
或许
MyParms.Add("OrganziationID", "=", droplist1.SelectedValue, SqlDbType.Int)
MyParms.SQL = "SELECT * from tblHotels"
再次说明:在运行上述1或2个条件后,注意?它正在会话中()
好吧,我们跳到另一页。现在我们需要填充一个网格
守则如下:
请注意,下面非常小心,我们如何不使用新关键字
Dim MyParms As SqlParms = Session("MyParms")
Dim rst As New DataTable
Using MyParms.cmdSQL
MyParms.cmdSQL.Connection.Open()
rst.Load(MyParms.cmdSQL.ExecuteReader)
End Using
GridView1.DataSource = rst
GridView1.DataBind()
因此,这个小“helper”例程允许您构建where子句。
它位于session()中,现在您可以将所有这些内容传递/跳转到另一个页面
另一件人们常常没有意识到的非常有趣的事情?
您始终可以向sql命令对象添加参数,但尚未设置sql集。你甚至不需要连接设置
所以,实际上您可以转储上面的“helper”例程,创建一个sql命令对象,并将其放入会话中
不管上述情况如何?您不必预先硬编码sql。这些值可以并且将成为参数安全的(sql注入安全的),如果您要添加“可选”参数,这甚至适用。唯一的诀窍是确保还使用这些可选参数构建sql
所以,如果我这样说:
dim MyParms as new SqlParms
MyParms.Add("City", "Like%", "E", SqlDbType.NVarChar)
MyParms.SQL = "SELECT * from tblHotels"
Dim rst As New DataTable
Using MyParms.cmdSQL
MyParms.cmdSQL.Connection.Open()
rst.Load(MyParms.cmdSQL.ExecuteReader)
End Using
GridView1.DataSource = rst
GridView1.DataBind()
因此,上面的内容将用结果表填充我们的数据网格
上面的sql现在是:
SELECT * from tblHotels WHERE (City Like @City + '%')
现在因为我想要“喜欢”的支持?嗯,我不能在参数名中添加/包含/包含%(我使用与前面带有@的字段名相同的名称)
因此,我使用%like(前缀通配符)
然后代码去掉%并按照上面的说明将其正确添加到where子句中
因此,在“添加”更多条件时,您可以/可以将字符串编码出来。但在所有情况下,使用参数不仅是一个好主意,而且也不是那么难做到
我在那个类中还使用了一个名为GetCon的公共函数,它只返回一个连接对象,但是你可以用你自己的例程替换这个类中的“GetCon”,这个例程返回一个连接字符串,然后用来创建一个sqlconneciton对象
另外,这是一个很小的问题,但我假设sql属性设置在最后,因为sql字符串随后与where子句组合在一起。如果添加更多参数,则需要再次设置sql属性
总之:
你可以也应该添加附加值作为参数。我看不出有什么理由不这样做
如果您需要在一个页面中设置所有这些,然后跳转到另一个页面,那么这个可爱的助手例程可以被推到会话中。(或者甚至让当前页面允许一些额外的过滤。那么,不可能在viewstate中存储一个参数化查询,然后在执行时在那里设置它的值吗?为什么不能在SQL代码中使用参数并将参数值添加到viewstate?然后在解密后,您可以创建一个命令和一个添加参数。我认为海报没有意识到你可以构建sql字符串,但可以动态地使用参数构建它们,从而获得参数安全的sql。我在下面的帖子中解释了如何实现。公平地说,我认为可以将sql命令对象推到会话中,因为该对象包含你的sql,包含你的参数,并且它只有一个对象。您甚至可以在该sql命令中保留连接对象。因此它相当不错。您必须通过存储过程
或参数化查询
来执行此操作。否则,您必须创建用于删除可疑字符的自定义函数,但当您已经拥有它时,不建议再次发明轮子ilt已经为您准备好了。显然,在这种情况下无法使用参数-th
SELECT * from tblHotels WHERE (City Like @City + '%')