zoukankan      html  css  js  c++  java
  • Ado.net 三[SQL注入,DataAdapter,sqlParameter,DataSet]

    1.SQL注入:SQL注入攻击是web应用程序的一种安全漏洞,可以将不安全的数据提交给运用程序,使应用程序在服务器上执行不安全的sql命令。使用该攻击可以轻松的登录运用程序。

       例如:该管理员账号密码为xiexun,该sql的正确语句应该为:

    select * from Users where userName='xiexun'

       如果在没有做任何处理的情况下,在登录名文本框中输入(xuxian' delete users--),单击"登录"按钮之后,相当于传了两句sql语句,一句执行查询之后,另外一句执行delete users之后整个表就没数据了,这样网站相当的不安全。

    select * from Users where userName='xiexun'  delete users--sql语句的注释,相当于把后面注释了

     解决办法:

     ①.通过@传参的方式[存储过程也是通过@传参],sqlParameter方法

    eg:

     public string Getswhere() 
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("select ID,username,PWD,loginname,qq,classname from Users  where 1=1");
                //获取到它的用户名
                string username = TxtUserName.Text.Trim();
                if (!string.IsNullOrEmpty(username))
                {
                    //sb.Append(string.Format("and username='{0}'", username));
                    //防SQL注入,通过@传参的方式
                    sb.Append(string.Format("and username=@username"));
                    //怎么把值传进去,通过sqlParameter数组
                    //SqlParameter[] para = new SqlParameter[]
                    //{
                    //    //创建一个SqlParameter对象(第一个传名称,第二个传值)
                    //    new SqlParameter("@username",username)
                    //};
                    // para[0]表示数组对象的第一个里面添加
                    //para[0] = new SqlParameter("@username",username);
    para.Add(new SqlParameter("@username", username));
    }
    if(ddlsclass.SelectedIndex>0) { //sb.Append(string.Format("and ClassName='{0}'", ddlsclass.SelectedValue)); sb.Append(string.Format("and ClassName=@ClassName")); //para[1] = new SqlParameter("@ClassName",ddlsclass.SelectedValue);
     para.Add(new SqlParameter("@ClassName", ddlsclass.SelectedValue)); }
    return sb.ToString(); }

             List<SqlParameter> para = new List<SqlParameter>();

            //我们把它放在list<>里,就有add方法

             private void openDB()
             {
              con = new SqlConnection(conStr);
              con.Open();//和数据库建立起了连接
              //我们单独把这两句话封装起来直接调用就好
             }
            //页面一运行就执行这里面的内容
            protected void Page_Load(object sender, EventArgs e)
            {
              BindUser();
            }

           public void BindUser()
            {
                try
                {
                    openDB();
                    //得到sql语句
                    //string sql = "select loginid,name,loginpwd,address,ClassName,mail from Users";
                    string sql = Getswhere();
                    //执行sql语句
                    using (cmd = new SqlCommand(sql, con))
                    //对象有了,我们要通过对象去执行sql语句
                    {
                        //调用它,通过遍历加到cmd里面去,我们把下面的值给cmd
                        //如果它里面有内容,我们就对它做一个循环
                        if (para.Count() > 0)
                        { 
                            foreach(var p in para)
                            {
                                cmd.Parameters.Add(p);
                            }
                        }
                        using (dr = cmd.ExecuteReader())
                        {
                            IdGridView.DataSource = dr;
                            IdGridView.DataBind();
                        }
                    }
                }
                catch 
                {
                    Response.Write("网站正在维护中.......!");
                }
            }

     这里,我们简单用一个图描述一下它的运行原理:前面的是没有通过@传参直接通过cmd与数据库交互的结果,不安全;后面一种是加了"Parameter"

          

       我们现在是把这个值new SqlParameter("@username",username)给sqlParameter数组,sqlparameter给cmd,cmd再执行,这样就可以避免SQL注入。

    2.DataAdapter数据适配器

      ①.工作原理:DataAdapter数据适配器相当于中间环节[中间人]

           

         ⅰ.前端页面委托数据适配器去实现和数据库的交互;

         ⅱ.数据库交互之后,再通过数据库适配器再把数据放内存里;

         ⅲ.然后我们的网页直接对内存里的东西读和写。(读的话可以直接读,写的话要再通过适配器把它加进去),这样数据库处于非正常连接的情况下也可以操作数据。

        而之前的写法:

          1.前端页面要和数据库交互,首先要建立起连接(数据库连接);

          2.用完之后要释放资源

         

      最大的好处就是:没有必要每一个页面都要与数据库进行连接,降低了数据库的压力。

      

      ②用数据适配器做一个查询[在程序中加存储过程]     

    <div>
              <asp:GridView ID="IdGridView" runat="server" AutoGenerateColumns="False">
                <Columns>
                    <asp:BoundField DataField="id" HeaderText="ID" />
                    <asp:BoundField DataField="username" HeaderText="用户名" />
                    <asp:BoundField DataField="PWD" HeaderText="密码" />
                    <asp:BoundField DataField="loginname" HeaderText="姓名" />
                    <asp:BoundField DataField="qq" HeaderText="QQ" />
                    <asp:BoundField DataField="classname" HeaderText="班级" />
                    <asp:TemplateField HeaderText="详情">
                        <ItemTemplate>
                            <a href="UserInfo.aspx?id=<%#Eval("ID") %>" target="_blank">详情</a>
                            <%--<a href='UserInfo.aspx?userid=<%#Eval("UserId") %>' target="_blank">详情</a
                           <%-- <a href="one.aspx?">详情</a>--%>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data;
    
    namespace _20160520
    {
        public partial class egDataAp : System.Web.UI.Page
        {
            private string conStr = ConfigurationManager.ConnectionStrings["mySchool"].ToString();
            SqlConnection con = null;//相当于是电话
            SqlCommand cmd = null;//执行sql语句
            SqlDataReader dr = null;//用于储存查询结果
            //首先创建一个DataSet
            DataSet ds = new DataSet();
            protected void Page_Load(object sender, EventArgs e)
            {
                //用数据适配器的方式做一个查询
                 con = new SqlConnection(conStr);
                string ssql = "select ID,username,PWD,loginname,qq,classname from Users";
                using(cmd = new SqlCommand(ssql, con))
                {
                    //创建一个DataAdapter,传一个cmd
                    SqlDataAdapter da = new SqlDataAdapter(cmd);
                    //应用数据适配器进行填充,填充到ds里
                    da.Fill(ds);
                    //指定一下数据源,.Tables[0]添加第一个table表
                    //IdGridView.DataSource = ds;
                    IdGridView.DataSource=ds.Tables[0];
                    IdGridView.DataBind();
                }
            }
        }
    }

      ③.DataAdapter调用存储过程[在数据库中加入存储过程调用]

     private string conStr = ConfigurationManager.ConnectionStrings["mySchool"].ToString();
            SqlConnection con = null;//相当于是电话
            SqlCommand cmd = null;//执行sql语句
            SqlDataReader dr = null;//用于储存查询结果
            //首先创建一个DataSet
            DataSet ds = new DataSet();
            protected void Page_Load(object sender, EventArgs e)
            {
                //用数据适配器的方式做一个查询
                con = new SqlConnection(conStr);
                //string ssql = "select ID,username,PWD,loginname,qq,classname from Users";
                //以上是之前的写法,这里我们直接传一个存储过程名
                using (cmd = new SqlCommand("procegDataAp", con))
                {
                    //指定一个sqlcommand的CommandType(默认情况下等于CommandType.text)为CommandType的存储过程名
                    cmd.CommandType = CommandType.StoredProcedure;
                    List<SqlParameter> para = new List<SqlParameter>() 
                    {
                        //通过sqlParameter数组把它加到cmd里面去,需指定名称,类型,值
                        //模糊查询
                        new SqlParameter("@UserName","%"+TxtsUserName.Text.Trim()+"%")
                    };
                    foreach(var a in para)
                    {
                        cmd.Parameters.Add(a);
                    }
                    //创建一个DataAdapter,传一个cmd
                    SqlDataAdapter da = new SqlDataAdapter(cmd);
                    //应用数据适配器进行填充,填充到ds里
                    da.Fill(ds);
                    //指定一下数据源,.Tables[0]添加第一个table表
                    //IdGridView.DataSource = ds;
                    IdGridView.DataSource = ds.Tables[0];
                    IdGridView.DataBind();
                }
            }

    3.DataSet,DataTable,DataReader,DataAdapter的区别:

       ⅰ.DtaSet是用来做sql连接的一种方法,意思是把数据库的副本存在应用程序里,相当于存在内存中的数据库,应用程序开始运行时,把数据库相关数据保存到DataSet.

       ⅱ.DataTable表示内存中数据的一个表,常和DefaultView使用获取可能包括筛选视图或游标位置的表的自定义视图。

       ⅲ.DataReader对象是用来读取数据库最简单的方式,它只能读取不能写入,而且是从头至尾往下读,无法只读某条数据,但它占用内存小,速度快.

       ⅳ.DataAdapter对象是用来读取数据库,可读取写入数据,某条数据操作强,但它占用内存比DataReader大,速度慢,一般和DataSet连用

       注.DataSet表示一个数据集,是数据在内存中的缓存。可以包含多个表DataTable,DataSet连接数据时是非面向连接的,把表全部读到sql中的缓存池,并断开于数据库的连接,DataReader连接数据库是面向连接的。读表时,只能向前读取,读完数据后友用户决定是否断开连接。

  • 相关阅读:
    [Unity3D] 如何将飞飞游戏资源提取并加载到uinty3d中
    [Unity3D] 解决提示参数动作文件不存在的错误Parameter 'XXX' does not exist.
    [Unity3D] 字体垂直自动滚动&鼠标拖拽滑动字体滚动
    [Unity3D] 图集按照顺序显示(幻灯片效果)&指定间隔时间显示
    [Unity3D] 在UI界面上显示播放视频
    TypeScript
    Css 设置超过再两行显示省略号
    vue scss 样式穿透
    JavaScript 严格模式(strict mode)
    Webpack file-loader 和 url-loader
  • 原文地址:https://www.cnblogs.com/wangwangwangMax/p/5551614.html
Copyright © 2011-2022 走看看