zoukankan      html  css  js  c++  java
  • 防止sql注入的参数化查询

    参数化查询为什么能够防止SQL注入

    http://netsecurity.51cto.com/art/201301/377209.htm

    OleDbDataAdapter Class
    http://msdn.microsoft.com/en-us/library/system.data.oledb.oledbdataadapter.aspx

    Sql Server 编译、重编译与执行计划重用原理
    http://www.2cto.com/database/201301/183262.html

     

    SQL语句很强大,很多时候需要拼凑SQL语句来完成某些功能,比如执行查询时候

    SELECT * FROM Customers where CustomerID  like  '%inputCustomerId%' or CompanyName like '%inputCompanyName%'




    假如有意使用途中字符串,会导致所有表中记录都能查询出来,为了避免这样的情况,需要使用参数化查询
    1.首先想到使用store procedure

    		Dim objCommand As OleDb.OleDbCommand
                    objCommand = New OleDb.OleDbCommand
                    With objCommand
                        .CommandText = "Test_StoreProcedure"
                        .Connection = connDbConnection
                        .CommandType = CommandType.StoredProcedure
                        .Parameters.AddWithValue("@CustomerId", customerId)
    
    		    .Parameters.AddWithValue("@CompanyName", companyName)
    		    .Parameters.AddWithValue("@ContactName", contactName)
                    End With
     
                    Dim ds As DataSet
                    Dim objAdaptor As OleDb.OleDbDataAdapter
                    objAdaptor = New OleDb.OleDbDataAdapter
                    ds = New DataSet
                    objCommand.Connection = connDbConnection
                    objAdaptor.SelectCommand = objCommand
                    objAdaptor.Fill(ds)
    可是在store procedure 内部,依然需要拼凑出sql语句来返回结果,等于什么作用都没起
    
    2.利用DataView
    
    	    Dim dv As DataView = New DataView(dt)
                dv.FindRows("customerid like '%" + customerId + "'%")
    可以看到这种方式仍然是拼凑条件字符串,不会起作用
    
    3.利用CommandType.Text的OleDbCommand不需要结果集可以用objCommand.ExecuteNonQuery()
    
    		Dim objCommand As OleDb.OleDbCommand                
    		objCommand = New OleDb.OleDbCommand                
    		With objCommand                   
    		    .CommandText = "select * from customer where customerid like ? or companyname like ? or contactname like ?"                   
    		    .Connection = connDbConnection                    .CommandType = CommandType.Text
                        .Parameters.AddWithValue("@CustomerId", customerId)
    
    		    .Parameters.AddWithValue("@CompanyName", companyName)
    		    .Parameters.AddWithValue("@ContactName", contactName)
                    End With
     
                    Dim ds As DataSet
                    Dim objAdaptor As OleDb.OleDbDataAdapter
                    objAdaptor = New OleDb.OleDbDataAdapter
                    ds = New DataSet
                    objCommand.Connection = connDbConnection
                    objAdaptor.SelectCommand = objCommand
                    objAdaptor.Fill(ds)
    
    4.直接利用OleDbDataAdapter的SelectCommand.Parameters,返回dataset
      		Dim sql As String = "select * from customer where customerid like ? or companyname like ? or contactname like ?"
    		Dim objAdaptor As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(sql, connDb)
    
    		objAdaptor.SelectCommand.Parameters.AddWithValue("@CustomerId""%" + customerId + "%")
                    objAdaptor.SelectCommand.Parameters.AddWithValue("@CompanyName""%" + companyName + "%")
                    objAdaptor.SelectCommand.Parameters.AddWithValue("@ContactName""%" + contactName + "%")
    		objAdaptor.Fill(ds)
    
    在数据库端看到的执行语句会包含有参数的类型,如下
    exec sp_executesql N'select * from customer where customerid LIKE @P1 and companyname LIKE @P2  and inputDate >= @P3 ',N'@P1 nvarchar(2),@P2 nvarchar(2),@P3 datetime',N'%%',N'%%','1900-01-02 00:00:00'
    
    
    5.利用System.Data.Linq
    DataContext db = new DataContext();
    IQueryable<Customer> custs = db.Customers;
    custs = custs.Where(o=>o.CustomerId.Contains(customerId));
    custs = custs.Where(o=>o.CompanyName.Contains(companyName));
    custs = custs.Where(o=>o.ContactName.Contains(contactName0);
    如果传进去的customerId包含like等语句,则这个linq语句不能成功解析出对应的sql语句,会报错
    
    6.很多时候数据库太复杂,需要用到各种数据库函数的时候,我们既想要利用sql语句来拼装,又不愿意冒着参数注入的危险,可以先用IQueryable<>或者IEnumerable<>来得到结果后再用where进行过滤
    IEnumerable<Customer> custs = db.ExecuteQuery<Customer>("select top 5 * from customer");
    custs = custs.Where(o=&gt;o.CustomerId.Contains(customerId));
     
  • 相关阅读:
    【磁盘/文件系统】第五篇:CentOS7.x__btrfs文件系统详解
    【python】-- IO多路复用(select、poll、epoll)介绍及实现
    【python】-- 事件驱动介绍、阻塞IO, 非阻塞IO, 同步IO,异步IO介绍
    【python】-- 协程介绍及基本示例、协程遇到IO操作自动切换、协程(gevent)并发爬网页
    【python】-- 多进程的基本语法 、进程间数据交互与共享、进程锁和进程池的使用
    【python】-- 队列(Queue)、生产者消费者模型
    【python】-- 信号量(Semaphore)、event(红绿灯例子)
    【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)
    【python】-- 继承式多线程、守护线程
    【python】-- 进程与线程
  • 原文地址:https://www.cnblogs.com/sui84/p/6777128.html
Copyright © 2011-2022 走看看