Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在vb.net中不使用参数使sql字符串安全_C#_Asp.net_.net_Vb.net_Sql Injection - Fatal编程技术网

C# 如何在vb.net中不使用参数使sql字符串安全

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 &

我正在从事一个用vb.net编写的项目,该项目有一个sql InInInjection问题,我几乎通过使用
参数解决了所有注入问题,有一种情况是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 + '%')