ListView 无法通过 ASP.net C# 中的 SQL 选择查询正确提供数据

问题描述 投票:0回答:1

我有一个 ASP.net C# 站点。我用这段代码将其中一个 ListView 提供给它,它就工作了:

protected void BindData()
{
    string forwardedSearchText = Request.QueryString["SearchText"];
    string forwardedSearchColumn = Convert.ToString(Session["SearchTitle"]);

    string strsql = "Select TbSoore.IdSoore, TbSoore.NameSoore, TbAye.NumberAye, TbAye.IdAye, TbAye.TextAye, TbAye.TextTarjome From TbAye INNER JOIN TbSoore ON TbAye.IdSoore = TbSoore.IdSoore Where FreeText((" + forwardedSearchColumn + "),N' " + forwardedSearchText + "')";

    DataTable dt = new DataTable();
    using (SqlConnection con = new SqlConnection(strcon))
    {
        using
            (SqlCommand cmdSQL = new SqlCommand(strsql, con))
        {
            con.Open();
            ListViewSearchResults.DataSource = cmdSQL.ExecuteReader();
            ListViewSearchResults.DataBind();
        }
    }

}

现在我想将查询字符串样式更改为更好的安全性:

$@"Select TbSoore.IdSoore, TbSoore.NameSoore, TbAye.NumberAye, TbAye.IdAye, TbAye.TextAye, TbAye.TextTarjome From TbAye INNER JOIN TbSoore ON TbAye.IdSoore = TbSoore.IdSoore Where FreeText(({forwardedSearchColumn}),N' @forwardedSearchText ')";

因此将

BindData()
更改为:

protected void BindData()
{
    string forwardedSearchText = Request.QueryString["SearchText"];
    string forwardedSearchColumn = Convert.ToString(Session["SearchTitle"]);

    string strsql = $@"Select TbSoore.IdSoore, TbSoore.NameSoore, TbAye.NumberAye, TbAye.IdAye, TbAye.TextAye, TbAye.TextTarjome From TbAye INNER JOIN TbSoore ON TbAye.IdSoore = TbSoore.IdSoore Where FreeText(({forwardedSearchColumn}),N' @forwardedSearchText ')";

    DataTable dt = new DataTable();
    using (SqlConnection con = new SqlConnection(strcon))
    {
        using
            (SqlCommand cmdSQL = new SqlCommand(strsql, con))
        {
            cmdSQL.Parameters.Add("@forwardedSearchText", SqlDbType.NVarChar).Value = forwardedSearchText;
            con.Open();
            ListViewSearchResults.DataSource = cmdSQL.ExecuteReader();
            ListViewSearchResults.DataBind();
        }
    }

}

但这不起作用。我没有收到任何错误,但表是空的。

有人可以帮助我吗?

c# asp.net listview sqlconnection
1个回答
0
投票

一个很好的例子,说明如何在代码中格式化 SQL 文本,并且不让它扭曲页面,确保在阅读代码时,您可以轻松地看到所有文本。

我会考虑使用视图,甚至更好的存储过程,这样就可以消除由于难以读取内联 SQL 而导致的此错误。

SQL 参数不使用也不需要引号。

我建议这样:

    protected void BindData()
    {
        string forwardedSearchText = Request.QueryString["SearchText"];
        string forwardedSearchColumn = Convert.ToString(Session["SearchTitle"]);

        string strsql = 
            $@"Select TbSoore.IdSoore, TbSoore.NameSoore, TbAye.NumberAye, TbAye.IdAye, TbAye.TextAye,
            TbAye.TextTarjome From TbAye
            INNER JOIN TbSoore ON TbAye.IdSoore = TbSoore.IdSoore
            Where FreeText({forwardedSearchColumn},@forwardedSearchText)";

        DataTable dt = new DataTable();
        using (SqlConnection con = new SqlConnection(strcon))
        {
            using
                (SqlCommand cmdSQL = new SqlCommand(strsql, con))
            {
                cmdSQL.Parameters.Add("@forwardedSearchText", SqlDbType.NVarChar).Value = forwardedSearchText;
                con.Open();
                ListViewSearchResults.DataSource = cmdSQL.ExecuteReader();
                ListViewSearchResults.DataBind();
            }
        }

    }

此外,如果 ListView 在数据绑定期间需要使用完整行(例如通常用于格式化每行),则向 ListView 提供读取器将不允许在绑定过程中使用完整数据行。

所以,我建议:

   cmdSQL.Parameters.Add("@forwardedSearchText", SqlDbType.NVarChar).Value = forwardedSearchText;
   con.Open();
   DataTable dt = new DataTable();
   dt.Load(cmdSQL.ExecuteReader());

   ListViewSearchResults.DataSource = dt;
   ListViewSearchResults.DataBind();

通过上述方法,我们减少了搜索词的字符串连接,但仍然存在注入漏洞。

问题当然是SearchColumn仍然是一个串联表达式,但更糟糕的是t-sql不允许列名作为参数。

如果该列只能是一列,那么我建议对该列进行硬编码,甚至为给定的列名称引入 switch case 语句。

如果列数是可变的(并且可以多于一列),那么至少确保此选择是某种列表框,或用户不输入列名称的其他类型的 UI。

如上所述,这些列名称的串联仍然存在安全风险。

因此,我将确保您的 UI 的列选择不允许列名称使用自由格式(文本框输入)。

© www.soinside.com 2019 - 2024. All rights reserved.