zoukankan      html  css  js  c++  java
  • 简单的web三层架构系统【第二版】

    昨天写了 web三层架构的第一版,准确的说是三层架构的前期,顶多算是个二层架构,要慢慢完善。

    第一版里,程序虽说能运行起来,但是有一个缺陷,就是里面的SQL语句,是使用的拼接字符进行执行。这样安全系数很低,如果有心人的话,可能会SQL注入,重新拼接字符,然后篡改我们的数据库内容,导致不可挽回的损失。

    在第二版本,也就是这一版里,我对原来的SQL语句进行了重构,使用带参数的SQL语句对数据库进行操作,这样做的好处是,无论用户输入的是什么格式的字符,SQL语句都会原封不动的把这些字符写入到数据库中,这样就避免了有心人对字符进行拼接,导致数据库出错。

    下面我用另一个小例子来说明防止SQL注入的核心代码,在最后会给出我重构过的第一版程序,也就是今天要写第二版程序:

    这是DAO类中的insert方法:

     1         public bool insert(string name, string sex, string salary)
     2         {
     3             bool flag = false;
     4 
     5             SqlParameter[] paras = new 6             {
     7                 new SqlParameter("@name", name),
     8                 new SqlParameter("@sex", sex),
     9                 new SqlParameter("@salary", salary)
    10             };
    11 
    12             string sql = "insert into person ([name], sex, salary) values (@name, @sex, @salary)";
    13 
    14             if (sq.ExecuteNonQuery(sql, paras) > 0)    //把SQL语句和SQL参数同时传入SQLHelper的ExecuteNonQuery中执行。
    15             {                   //16                 flag = true;
    17             }
    18 
    19             return flag;
    20    }

    这是SQLHelper类中的ExecuteNonQuery方法:

     1         public int ExecuteNonQuery(string sql, SqlParameter[] paras)
     2         {
     3             int result;
     4 
     5             cmd = new SqlCommand(sql, getcon());    //创建SQLcommand对象cmd
     6 
     7             cmd.Parameters.AddRange(paras);         //在SQLcommand对象cmd中,添加参数。
     8                               //上面的这一句注释,是自己的理解,如果理解错了,请在评论区帮忙指正一下,先谢过。
     9             result = cmd.ExecuteNonQuery();         //然后执行对象cmd,其中已经包含了SQL语句和要用的参数
    10 
    11             return result;
    12       }

    上面是一个小例子,创建了一张表,然后向表里的 NAME SEX SALARY 三个字段中添加内容。

    下面是第二版web三层架构程序:

    SQLhelper助手类:

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 
      7 using System.Data;
      8 using System.Data.SqlClient;
      9 using System.Configuration;
     10 
     11 namespace DAL
     12 {
     13     public class SQLHelper
     14     {
     15         SqlCommand cmd = null;
     16 
     17         public string strcon()
     18         {
     19             string strcon = ConfigurationManager.ConnectionStrings["strcon"].ConnectionString;
     20 
     21             return strcon;
     22         }
     23 
     24         public SqlConnection getcon()
     25         {
     26             SqlConnection con = new SqlConnection(strcon());
     27 
     28             if (con.State == ConnectionState.Closed)
     29             {
     30                 con.Open();
     31             }
     32 
     33             return con;
     34         }
     35 
     36         #region 执行增删改查的SQL语句
     37         /// <summary>
     38         /// 执行增删改查的SQL语句
     39         /// </summary>
     40         /// <param name="sql">要执行的SQL</param>
     41         /// <returns>返回执行SQL语句后影响的行数</returns>
     42         public int ExecuteNonQuery(string sql)
     43         {
     44             int res;
     45 
     46             try
     47             {
     48                 cmd = new SqlCommand(sql, getcon());
     49 
     50                 res = cmd.ExecuteNonQuery();
     51             }
     52             catch (Exception ex)
     53             {
     54                 throw ex;
     55             }
     56             finally
     57             {
     58                 if (getcon().State == ConnectionState.Open)
     59                 {
     60                     getcon().Close();
     61                 }
     62             }
     63 
     64             return res;
     65         }
     66         #endregion
     67 
     68         #region 执行带参数的增删改SQL语句
     69         /// <summary>
     70         /// 执行带参数的增删改SQL语句
     71         /// </summary>
     72         /// <param name="sql">要执行的SQL语句</param>
     73         /// <param name="paras">传入的参数</param>
     74         /// <returns>返回受影响的行数</returns>
     75         public int ExecuteNonQuery(string sql, SqlParameter[] paras)//上下两个ExecuteNonQuery因为使用了方法的重载,其中参数不同,所以虽说都在调用ExecuteNonQuery,但是传递的参数的个数不同,系统会自动识别用哪一个ExecuteNonQuery方法。
     76         {
     77             int res;
     78 
     79             cmd = new SqlCommand(sql, getcon());//  1  
     80 
     81             cmd.Parameters.AddRange(paras);//  2  
     84 
     85             res = cmd.ExecuteNonQuery();
     86 
     87             return res;
     88         }
     89         #endregion
     90 
     91         #region 执行传入的SQL查询语句
     92         /// <summary>
     93         /// 执行传入的SQL查询语句
     94         /// </summary>
     95         /// <param name="sql">要执行的查询SQL</param>
     96         /// <returns>返回查询SQL语句的数据集</returns>
     97         public DataTable ExecuteQuery(string sql)
     98         {
     99             DataTable dt = new DataTable();
    100 
    101             //创建一个SqlCommand对象cmd,让其连接数据库,并指向sql语句。//自己理解,如果不对的话请在评论区指正,先谢过。
    102             cmd = new SqlCommand(sql, getcon());
    103 
    104             //执行cmd连接的数据库.使用using后在执行完毕后,直接关闭sdr。不需要写sdr.closed.
    105             using (SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))//如果使用 CommandBehavior.CloseConnection 参数,那么在代码的结尾处就不需要写 getcon().Close(),他会直接关闭。
    106             {
    107                 dt.Load(sdr);// Load 这种方法适合于SqlDataReader。如果是SqlDataAdapter,则会用到 Fill 方法。
    108             }
    109 
    110             return dt;
    111         }
    112         #endregion
    113 
    114         #region 执行传入带参数的SQL查询语句
    115         /// <summary>
    116         ///  执行传入带参数的SQL查询语句
    117         /// </summary>
    118         /// <param name="sql">要执行的SQL语句</param>
    119         /// <param name="paras">传入的参数</param>
    120         /// <returns>返回查询的数据集</returns>
    121         public DataTable ExecuteQuery(string sql, SqlParameter[] paras)
    122         {
    123             DataTable dt = new DataTable();
    124 
    125             cmd = new SqlCommand("sql", getcon());
    126 
    127             cmd.Parameters.AddRange(paras);
    128 
    129             using (SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
    130             {
    131                 dt.Load(sdr);
    132             }
    133 
    134             return dt;
    135         }
    136         #endregion
    137     }
    138 }

    personDAO员工操作类:

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 
      7 using System.Data;
      8 using System.Data.SqlClient;
      9 
     10 namespace DAL
     11 {
     12     public class personDAO
     13     {
     14         SQLHelper sq = null;
     15 
     16         public personDAO()
     17         {
     18             sq = new SQLHelper();
     19         }
     20 
     21         #region 增加员工信息
     22         /// <summary>
     23         /// 增加员工信息
     24         /// </summary>
     25         /// <param name="name">要添加的员工姓名</param>
     26         /// <param name="sex">要添加的员工性别</param>
     27         /// <param name="salary">要添加的员工工资</param>
     28         /// <returns>返回真假值:如果是真显示添加成功,如果是假显示添加失败</returns>
     29         public bool insert(string name, string sex, string salary)
     30         {
     31             bool flag = false;
     32 
     33             SqlParameter[] paras = new SqlParameter[]
     34             {
     35                 new SqlParameter("@name", name),
     36                 new SqlParameter("@sex", sex),
     37                 new SqlParameter("@salary", salary)
     38             };
     39 
     40             string sql = "insert into person ([name], sex, salary) values (@name, @sex, @salary)";//记住,添加参数的时候,不需要 双引号 或是 单引号。
     41 
     42             if (sq.ExecuteNonQuery(sql, paras) > 0)//把sql语句和所用到参数数组,一起传送到 ExecuteNonQuery 中去执行。
     43             {
     44                 flag = true;
     45             }
     46 
     47             return flag;
     48         }
     49         #endregion
     50 
     51         #region 删除员工信息
     52         /// <summary>
     53         /// 删除员工信息
     54         /// </summary>
     55         /// <param name="id">要删除员工的id</param>
     56         /// <returns>返回真假值:如果是真显示删除成功,如果是假显示删除失败</returns>
     57         public bool delete(string id)
     58         {
     59             bool flag = false;
     60 
     61             SqlParameter[] paras = new SqlParameter[]
     62             {
     63                 new SqlParameter("@id", id)
     64             };
     65 
     66             string sql = "delete from person where id = @id";//记住,添加参数的时候,不需要 双引号 或是 单引号。
     67 
     68             if (sq.ExecuteNonQuery(sql, paras) > 0)
     69             {
     70                 flag = true;
     71             }
     72 
     73             return flag;
     74         }
     75         #endregion
     76 
     77         #region 更改员工信息
     78         /// <summary>
     79         /// 更改员工信息
     80         /// </summary>
     81         /// <param name="id">要更改的员工编号</param>
     82         /// <param name="name">要更改的员工姓名</param>
     83         /// <param name="sex">要更改的员工性别</param>
     84         /// <param name="salary">要更改的员工工资</param>
     85         /// <returns>返回真假值:如果是真显示更改成功,如果是假显示更改失败</returns>
     86         public bool update(string id, string name, string sex, string salary)
     87         {
     88             bool flag = false;
     89 
     90             SqlParameter[] paras = new SqlParameter[]//创建参数数组
     91             {
     92                 new SqlParameter("@id", id),//我的理解:对参数数组赋值
     93                 new SqlParameter("@name", name),
     94                 new SqlParameter("@sex", sex),
     95                 new SqlParameter("@salary", salary)
     96             };
     97 
     98             //使用参数数组
     99             string sql = "update person set [name] = @id, sex = @name, salary = @sex where id = salary";//记住,添加参数的时候,不需要 双引号 或是 单引号。
    100 
    101             if (sq.ExecuteNonQuery(sql, paras) > 0)
    102             {
    103                 flag = true;
    104             }
    105 
    106             return flag;
    107         }
    108         #endregion
    109 
    110         #region 判断员工姓名是否重复
    111         /// <summary>
    112         /// 判断员工姓名是否重复
    113         /// </summary>
    114         /// <param name="name">要进行判断的员工姓名</param>
    115         /// <returns>返回真假值:如果是真代表重复,如果是假进行添加</returns>
    116         public bool repeat(string name)
    117         {
    118             bool flag = false;
    119 
    120             SqlParameter[] paras = new SqlParameter[]
    121             {
    122                 new SqlParameter("@name", name)
    123             };
    124 
    125             string sql = "select * from person where [name] = @name";//记住,添加参数的时候,不需要 双引号 或是 单引号。
    126 
    127             #region 下面这样写的话,还要重新建立一张虚拟表,如果直接用下面的方法,进行行数的判断就不需要建立。
    128             //DataTable dt = sq.ExecuteQuery(sql);
    129 
    130             //if (dt.Rows.Count > 0)//dt.Rows.Count 这个方法是检查返回的虚拟表中是不是有数据,如果有的话则行数不为零。如果没有的话则行数为零。
    131             //{
    132             //    flag = true;
    133             //}
    134             #endregion
    135 
    136             if (sq.ExecuteQuery(sql, paras).Rows.Count > 0)//dt.Rows.Count 这个方法是检查返回的虚拟表中是不是有数据,如果有的话则行数不为零。如果没有的话则行数为零。
    137             {
    138                 flag = true;
    139             }
    140 
    141             return flag;
    142         }
    143         #endregion
    144     }
    145 }

    上面就是重构的第一版的代码,也就是第二版,其中如果有错误的地方,请在评论区帮忙指正。

  • 相关阅读:
    10.13_extjs,combox,效率为什么这么低
    10.12_win8风格,把专业书籍当小说看,SQLite
    10.11_魔兽世界
    10.10_魔兽账号,OSC代码托管演示,研究SQL别忘记了,git
    10.09_命名:包名、类名、方法名
    10.08_逛逛OSC
    国庆第七日(2014年10月7日17:55:56),随手记,一些关注的OSC软件,花生壳
    国庆第六日(2014年10月6日11:51:15),node-webkit,理财产品
    国庆第五日2014-10-05 10:03,电子书
    truffle框架快速开发合约步骤
  • 原文地址:https://www.cnblogs.com/KTblog/p/4189859.html
Copyright © 2011-2022 走看看