MVC 4 SQL 字符串注入安全

MVC 4 SQL string injection Security

您好,我是 MVc 和 C# 的新手,我想知道是否可以使用模型安全性来防止 SQL 注入?我创建了一个模型,其中包含我们从客户输入中收到的变量,然后从中形成一个 SQL 语句。我想知道 MVC 中内置的安全性是否足以防止 SQL 注入?请查看代码,非常感谢任何建议。

型号

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace DataBaseTest.Models
{
   public class BedroomModel
   {
    public string YrBlt1 { get; set; }
    public string YrBlt2 { get; set; }
    public string TotLivArea1 { get; set; }
    public string TotLivArea2 { get; set; }
    public string LotArea1 { get; set; }
    public string LotArea2 { get; set; }
    public string Bedrooms { get; set; }
    public string SalePrice1 { get; set; }
    public string SalePrice2 { get; set; }
    public string SaleDate { get; set; }
    public string AssesVal1 { get; set; }
    public string AssesVal2 { get; set; }
    public string Style { get; set; }
    public string ArchStyle { get; set; }
    public string TaxUnit { get; set; }

    // Criteria added during SQL Queries
    public string YearBuilt { get; set; }
    public string LivingArea{ get; set; }
    public string LotArea { get; set; }
    public string SalePriceA { get; set; }
    public string SaleDateA { get; set; }
    public string AssesVal { get; set; }
    public string StyleA { get; set; }
    public string ArchStyleA { get; set; }
    public string ParcelId { get; set; }
    public string QuickRefId { get; set; }
    public string TaxunitA { get; set; }
    public string Address { get; set; }
    public string ValCode { get; set; }
    public string BedroomA { get; set; }  

然后我们的SQL

  [HttpPost]
    public ActionResult Index(DataBaseTest.Models.BedroomModel user,DataTable dtFindResults)
    {
        StringBuilder sbSQL = new StringBuilder();
        //// define a list of CustomerModel objects
        DataSet tempDS = new DataSet();

        //string xSQL = "SELECT PropertyAddress,PropertyTypeDesc,PropertyID FROM KDOR_vwPropertyGeneral ORDER BY PropertyAddress";
        System.Data.SqlClient.SqlDataAdapter DbCmd = new System.Data.SqlClient.SqlDataAdapter();
        string sqlWhereCont = " WHERE ";
        sbSQL.Append("SELECT ");
        //sbSQL.Append(SessionHandler.AddressPointsPointsIDColumn + " AS PointsID,");
        sbSQL.Append("pg.PropertyNumberSearch,");
        sbSQL.Append("pg.QuickRefID,");
        sbSQL.Append("pg.PropertyAddress,");
        sbSQL.Append("crb.fmsstyle,");
        sbSQL.Append("srb.farchstyle,");
        sbSQL.Append("pt.TransferValidityCode,");
        sbSQL.Append("pg.TaxingUnitGroupCode,");
        sbSQL.Append("pt.Price,");
        sbSQL.Append("pt.SaleDate,");
        sbSQL.Append("crb.fyrblt,");
        sbSQL.Append("crb.vResBldgDep_tla_value,");
        sbSQL.Append("lm.facres,");
        sbSQL.Append("crb.frmbed");
        sbSQL.Append(" FROM KDOR_vwPropertyGeneral pg ");
        sbSQL.Append(" Left Join cama_ResBldg crb ON pg.PropertyID = crb.PropertyID And pg.AdHocTaxYear = crb.AdHocTaxYear ");
        sbSQL.Append(" Left Join sales_ResBldg  srb ON pg.PropertyID = srb.PropertyID");
        sbSQL.Append(" Left Join KDOR_vwPropertyTransfer pt On pg.PropertyID = pt.PropertyID");
        sbSQL.Append(" Left Join cama_LandMkt lm ON pg.PropertyID = lm.PropertyID And pg.AdHocTaxYear = lm.AdHocTaxYear");
        if (!string.IsNullOrEmpty(user.YrBlt1)||!string.IsNullOrEmpty(user.YrBlt2))
        {
            //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'");
            //sqlWhereCont = "AND ";
            sbSQL.Append(sqlWhereCont +"crb.fyrblt >="+ user.YrBlt1+ " And crb.fyrblt <=  " + user.YrBlt2 );
            sqlWhereCont = "AND ";
        }
        if (!string.IsNullOrEmpty(user.TotLivArea1) || !string.IsNullOrEmpty(user.TotLivArea2))
        {
            //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'");
            //sqlWhereCont = "AND ";
            sbSQL.Append(sqlWhereCont + "crb.vResBldgDep_tla_value >=" + user.TotLivArea1 + " And crb.vResBldgDep_tla_value <=  " + user.TotLivArea2 );
            sqlWhereCont = "AND ";
        }
        if (!string.IsNullOrEmpty(user.LotArea1) || !string.IsNullOrEmpty(user.LotArea2))
        {
            //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'");
            //sqlWhereCont = "AND ";
            sbSQL.Append(sqlWhereCont + "lm.facres >=" + user.LotArea1 + " And lm.facres <= " + user.LotArea2 );
            sqlWhereCont = "AND ";
        }

        if (!string.IsNullOrEmpty(user.Bedrooms))
        {
            sbSQL.Append(sqlWhereCont + "crb.frmbed = '" + user.Bedrooms + "'");
            sqlWhereCont = "AND ";
        }
        if (!string.IsNullOrEmpty(user.SalePrice1) || !string.IsNullOrEmpty(user.SalePrice2))
        {
            //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'");
            //sqlWhereCont = "AND ";
            sbSQL.Append(sqlWhereCont + "pt.Price >=" + user.SalePrice1 + " And pt.Price <=  " + user.SalePrice2 );
            sqlWhereCont = "AND ";
        }
        if (!string.IsNullOrEmpty(user.SaleDate))
        {
            sbSQL.Append(sqlWhereCont + "pt.SaleDate = '" + user.SaleDate + "'");
            sqlWhereCont = "AND ";
        }
        if (!string.IsNullOrEmpty(user.AssesVal1) || !string.IsNullOrEmpty(user.AssesVal2))
        {
            //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'");
            //sqlWhereCont = "AND ";
            sbSQL.Append(sqlWhereCont + "crb.vResBldgDep_tla_value >=" + user.AssesVal1 + " And crb.vResBldgDep_tla_value <= " + user.AssesVal2 );
            sqlWhereCont = "AND ";
        }
        if (!string.IsNullOrEmpty(user.Style))
        {
            sbSQL.Append(sqlWhereCont + "crb.fmsstyle = '" + user.Style + "'");
            sqlWhereCont = "AND ";
        }
        if (!string.IsNullOrEmpty(user.ArchStyle))
        {
            sbSQL.Append(sqlWhereCont + "srb.farchstyle = '" + user.ArchStyle + "'");
            sqlWhereCont = "AND ";
        }
        if (!string.IsNullOrEmpty(user.TaxUnit))
        {
            sbSQL.Append(sqlWhereCont + "pg.TaxingUnitGroupCode = '" + user.TaxUnit + "'");
            sqlWhereCont = "AND ";
        }
        sbSQL.Append(" ORDER BY ");
        sbSQL.Append(" pg.QuickRefID ");


        //// populate a list of CustomerModel objects from database
        string MyConnectionString = ConfigurationManager.ConnectionStrings["WLConnection"].ConnectionString;
        System.Data.SqlClient.SqlConnection cnn = new System.Data.SqlClient.SqlConnection(MyConnectionString);
        System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sbSQL.ToString(), cnn);
        cmd.CommandTimeout = 30000;
        DbCmd.SelectCommand = cmd;
        DbCmd.Fill(tempDS, "ResultSet");
        DataTable resultSet = tempDS.Tables["ResultSet"];
        var vm = new List<BedroomModel>();
       foreach (DataRow dr in tempDS.Tables[0].Rows)
        {
            vm.Add(new BedroomModel 
            {
                BedroomA = dr.ItemArray[12].ToString(),
                YearBuilt = dr.ItemArray[9].ToString(),
                LivingArea = dr.ItemArray[7].ToString(),
                LotArea = dr.ItemArray[3].ToString(),
                SaleDateA = dr.ItemArray[8].ToString(),
                SalePriceA = dr.ItemArray[10].ToString(),
                AssesVal = dr.ItemArray[5].ToString(),
                StyleA = dr.ItemArray[3].ToString(),
                ArchStyleA = dr.ItemArray[4].ToString(),
                ParcelId = dr.ItemArray[0].ToString(),
                QuickRefId = dr.ItemArray[1].ToString(),
                TaxunitA = dr.ItemArray[6].ToString(),
                Address = dr.ItemArray[2].ToString(),
                ValCode = dr.ItemArray[5].ToString(),


             });
          }
        //DbCmd.Fill(dtFindResults);
        //var x = dtFindResults.Rows.Count;
        cnn.Close();
       return View("Result",vm);
        //// return the list of CustomerModel objects to our View
        //return View("Result", resultSet);
        //return View(ViewBag.data);
    }

参数化查询是必须的。但是,这并不妨碍您构建动态查询,您只需要采用不同的方法即可。

根据用户输入做出决定很好;将这些值连接到一个查询中好。

一个简单的例子:

using( IDbCommand cmd = GetCommand() )
{
    string lotSize = "12345";
    bool includeLotSize = !string.IsNullOrWhiteSpace( lotSize );

    var sb = new StringBuilder();
    sb.AppendLine( "SELECT Col1, Col2 FROM dbo.Foo" );

    // you might also vary the columns returned based on what the user asked for

    if( includeLotSize )
    {
        sb.AppendLine( "WHERE LotSize = @LotSize" );

        // The query will expect the lot size, so add a parameter here to pass 
        // the lot size value.
        cmd.Parameters.Add( new SqlParameter( "LotSize", lotSize ) );
    }
}

请注意,您的许多字符串属性看起来可能是更具体的类型(int、float、指向数据库查找的 int 等)。这不会阻止 SQL 注入,但它可用于验证(以及使您的视图模型更清洁)。

另请注意,有许多不同的方法可以连接到 .Net 中的数据库,但请确保正确处理资源(请注意我添加的 using 语句)。