【问题标题】:ASP.net VB search engineASP.net VB 搜索引擎
【发布时间】:2011-09-06 18:04:10
【问题描述】:

我有一个搜索引擎,它应该通过产品描述进行搜索,然后会显示包含用户正在寻找的任何单词或短语的产品列表。不过,我还没有为使用该描述的产品列出任何类型的列表。

我只需要弄清楚为什么我的 SELECT 语句没有做任何事情。要么是那个,要么是 For Each 循环。

这就是我所拥有的:

 Public Function GetDescriptions(ByVal prefixText As String, ByVal count As Integer) As String()
    Dim MarketingSql As String = "Select MarketingID, MarketingType, MarketingData FROM Marketing WHERE MarketingType = 2 AND MarketingData LIKE '%" & prefixText & "%'"
    Dim sqlConn As New SqlConnection
    sqlConn.Open()
    Dim myCommand As New SqlCommand(MarketingSql, sqlConn)
    Dim myReader As SqlDataReader = myCommand.ExecuteReader()
    Dim myTable As New DataTable
    myTable.TableName = "DescriptionSearch"
    myTable.Load(myReader)
    sqlConn.Close()
    Dim items As String() = New String(myTable.Rows.Count - 1) {}
    Dim i As Integer = 0
    For Each dr As DataRow In myTable.Rows
        items.SetValue(dr("MarketingData").ToString(), i)
        i += 1
    Next
    Return items
End Function


<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
<script type="text/javascript">
function AutoCompleteClientMethod(source, eventArgs) {
    var value = eventArgs.get_value();
    window.location = ("/Product/Default.aspx?id=" + value)
} 
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="body" Runat="Server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    <Services>
        <asp:ServiceReference Path="DescriptionSearch.asmx" />
    </Services>
</asp:ScriptManager>
    <asp:TextBox ID="Search" runat="server" AutoComplete="off"></asp:TextBox>
    <asp:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server" TargetControlID="Search" ServicePath="~/DescriptionSearch.asmx" ServiceMethod="GetDescriptions" MinimumPrefixLength="1" CompletionSetCount="255" EnableCaching="true" OnClientItemSelected="AutoCompleteClientMethod">
    </asp:AutoCompleteExtender>
</asp:Content>

【问题讨论】:

    标签: asp.net sql vb.net web-services foreach


    【解决方案1】:

    我立即发现您的代码存在三个问题:

    1. 正如您所说,您的代码容易受到 sql 注入的攻击。您将其上线,任何愿意尝试的人都将完全拥有您的数据库。这甚至不难。 “首先让它发挥作用”的策略是一种完全倒退和错误的方法来解决这个问题。像这样的代码经常会投入生产。
    2. 您正在使用 LIKE 运算符搜索冗长的文本列。这将消耗您的数据库性能。这是全文索引和CONTAINS 函数的好地方。搜索时间将是白天和黑夜。
    3. 您并不总是关闭数据库连接。如果抛出异常,您将泄漏打开的连接对象,这最终可能导致对您的数据库的有效拒绝服务攻击,该攻击源自您自己的应用程序。数据库连接必须始终包含在 try/finally 块中。

    这只是冰山一角,仅从略读中收集到的。我什至还没有开始深入阅读代码。


    这是一个更新(迟到了,我知道),基于修复 sql 注入问题的自我接受的答案:

     <WebMethod()> _
    Public Function GetDescriptions(ByVal prefixText As String, ByVal count As Integer)
    As List(Of String)
        Dim MarketingSql As String = "Select DISTINCT p.ProductID, p.ProductName 
          FROM Product p 
          INNER JOIN Marketing m ON p.ProductID = m.ProductID 
          INNER JOIN Picklist k ON k.PicklistID = m.MarketingData 
          WHERE m.MarketingTypeID = 2 AND k.Data LIKE '%' + @prefixText + '%' 
          ORDER BY p.ProductName ASC"
    
        Using sqlConn As New SqlConnection
          (System.Configuration.ConfigurationManager.ConnectionStrings
          ("LocalSqlServer").ConnectionString), _
              myCommand As New SqlCommand(MarketingSql, sqlConn)
    
            myCommand.Parameters.Add("@prefixText", SqlDbTypes.VarChar, 50).Value = prefixText
            sqlConn.Open()
            Using myReader As SqlDataReader = myCommand.ExecuteReader()
                While myReader.Read()
                    Dim id As String = myReader("ProductID").ToString()
                    Dim name As String = myReader("ProductName").ToString()
                    items.Add(AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(name, id))
                End While
             End Using
         End Using
         Return items
    End Function
    

    【讨论】:

    • @Nick - 刚刚看到你的评论。我去了哈丁大学。
    • @Joel lol 他在问我,但我删除了我的 cmets,因为我希望版主会删除这篇文章,因为我必须自己回答。
    • @jlg - 这解释了它。现在查看您答案中的代码,我发现您仍然存在巨大的 sql 注入漏洞:(
    • 感谢您的帮助,我试图将 prefixText 放入参数中,但我无法弄清楚。 :)
    【解决方案2】:

    这就是为项目更新 WebService 的方式。现在可以正常使用了。

     <WebMethod()> _
    Public Function GetDescriptions(ByVal prefixText As String, ByVal count As Integer)
    As String()
        Dim MarketingSql As String = "Select DISTINCT p.ProductID, p.ProductName 
    FROM Product p 
    INNER JOIN Marketing m ON p.ProductID = m.ProductID 
    INNER JOIN Picklist k ON k.PicklistID = m.MarketingData 
    WHERE m.MarketingTypeID = 2 AND k.Data LIKE '%' & @prefixText & '%' 
    ORDER BY p.ProductName ASC"
        Using sqlConn As New SqlConnection
          (System.Configuration.ConfigurationManager.ConnectionStrings
          ("LocalSqlServer").ConnectionString)
        sqlConn.Open()
        Dim myCommand As New SqlCommand(MarketingSql, sqlConn)
        myCommand.Parameters.Add("@prefixText", SqlDbType.VarChar, 50).Value = prefixText
        Dim myReader As SqlDataReader = myCommand.ExecuteReader()
        Dim myTable As New DataTable
        myTable.TableName = "DescriptionSearch"
        myTable.Load(myReader)
        sqlConn.Close()
        Dim items As String() = New String(myTable.Rows.Count - 1) {}
        Dim i As Integer = 0
        For Each dr As DataRow In myTable.Rows
            Dim id As String = dr("ProductID").ToString()
            Dim name As String = dr("ProductName").ToString()
            Dim item As String = AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(name, id)
            items.SetValue(item, i)
            i += 1
        Next
        Return items
        End Using
    End Function
    

    【讨论】:

    • 感谢@JoelCoehoorn 帮助我解决注射问题。
    【解决方案3】:

    除了 Joel 的 cmets,您真的真的需要永远不要将 Select 语句放入您的代码中(即使在测试时)......永远。始终使用存储过程。现在我需要做的就是阅读你的 web.config 文件(假设你没有花时间加密它),阅读你的连接,我可以完全访问你的所有数据。

    【讨论】:

    • 参数化查询也能创造奇迹。这是一种可怕的学习方式——问问你的学校为什么你比导师知道的更多。
    • 存储过程不是唯一的选择。很多替代方案,特别是在 OR/Ms(如 LINQ 和 NHibernate)方面都可以正常工作,而无需存储过程。至于现在作业比上学时多的问题,欢迎来到科技世界。为了生存,你必须不断学习新东西。
    • 另外,请随时使用我在thinqlinq.com/Default/… 描述的 LINQ 在我的网站上查看搜索实现。
    • 真的,真的吉姆。我很抱歉误导人们认为存储过程是唯一的其他选择。我只是想强调不要将语句放入代码中。我的错,哟。
    • 我的下一步是什么?因为我对安全一无所知,所以我想在这里采取一些小步骤,不要让自己不知所措,特别是因为完成这项工作非常重要。顺便说一句,这是一个内部站点,大约有 4 人使用,所以我们现在不太担心注射。制作现场网站的时候我会更担心,因为你们都指出了错误!
    猜你喜欢
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2016-12-31
    相关资源
    最近更新 更多