簡體   English   中英

如何在不使用參數的情況下使 sql 字符串在 vb.net 中安全

[英]How to make sql string safe in vb.net without using parameters

我正在做一個用vb.net編寫的項目,它有sql innjection問題,我幾乎通過使用parameters修復了所有注入,有一種情況是 sql 字符串被構建然后加密並傳遞給viewState ,然后它會檢索和解密從要運行的viewState來看,顯然這種情況下不能使用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

如何在不使用參數的情況下做到這一點? 我應該考慮和避免什么?

好吧,我認為問題在於人們假設您不能擁有“可選”參數,或者您必須提前設置它們。 (你沒有)。

你可以去列出這個:

dim strWhere  as string
strWhere = "(State =  @State)
cmdSQL.Parmaters.Add("@State",SqlDbType.NVarchar).Value = lstBrowse.SelectedItem.Value 

現在,我可以向 strWhere 添加更多條件“即時”,並且隨着時間的推移向 cmdSQL.Parmaters 集合添加參數。

現在,讓我們假設您在一些復雜的網格頁面上,並且用戶選擇了一些東西,現在您需要將這個 say 傳遞給另一個表單?

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 串連起來。 因此無需使用 EXISTING 參數對 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

那么,以上所有呢? 讓您添加一個“字段”、一個“條件”,然后再添加一些。 這很簡單。

所以,現在在代碼中,我可以去:

Dim MyParms As New SqlParms
Session("MyParms") = MyParms

現在,請注意我們曾經將 session 指向該類? 然后我可以在當前的代碼位中添加/修改,而​​不必漏斗/保存/推回 MyParms - 它是一個對象,現在在會話中。

所以,讓我們添加你的條件。

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條件后注意? 它在 session() 中。

好的,我們跳到了一個新的不同頁面。 現在我們需要填充一個網格。

代碼將是:

注意下面我們如何不使用 new 關鍵字非常非常小心!

    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()

所以這個小小的“助手”例程可以讓你建立 where 子句。 它在 session() 中,現在您可以將所有這些內容傳遞/跳轉到另一個頁面。

另一個非常有趣的事情,人們通常沒有意識到? 您始終可以向 sql 命令對象添加參數,但尚未設置 sql 集。 你甚至不需要連接集。

因此,您實際上可以轉儲上面的“幫助程序”例程,而只是創建一個 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(前綴通配符)和 Like%(后綴)。 然后代碼去掉 % 並將其正確添加到上述 where 子句中。

因此,您可以/可以在“添加”更多條件時對字符串進行編碼。 但在所有情況下,使用參數仍然不僅是一個好主意,而且並不難做到。

我在那個類中還使用了一個名為 GetCon 的公共函數,它只返回一個連接對象,但您可以只用您自己的例程替換該類中的“GetCon”,該例程返回一個連接字符串,然后用於創建一個 sqlconneciton 對象。

此外,相當小,但我確實假設 sql 屬性設置為 LAST,因為 sql 字符串然后與 where 子句組合。 如果添加更多參數,則需要再次設置 sql 屬性。

總結:您可以並且應該添加附加值作為參數。 我沒有太多理由不這樣做。

如果您需要在一個頁面中設置所有這些,然后跳轉到另一個頁面,那么可以將這個可愛的幫助程序推入會話中。 (甚至讓當前頁面允許說一些額外的過濾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM