一个逗号引发的数据库异常的思考
    之所以写这篇文章,完全是纪念我这无聊而又让我深思的一天。
    昨天晚上,收到王师兄一个电话,说学报网站出问题了,发布新闻发不上去。我当时还想,开什么国际玩笑,我去年曾反复测试过了,怎么会有问题呢,然后我把他那篇新闻拿过来上传,发现果然如他所说,点击“提交”时页面没有反应,一片空白。
    就这样看似一个小小的问题,却让我进行了之后一天的“发现之旅”,而当我发现问题的根本原因时才发现原来不过如此。
字符串截取逗号前面的    一、问题陈述
    首先说一下,数据库是用Access制作的,新闻大致用来这样几个字段:新闻标题(news_title)、新闻发布者(news_publisher)、发布日期(news_datetime)、新闻内容(news_content)、是否加亮显示(news_flag)等等。
    要发布新闻,程序要做的步骤是:1.建立数据库连接并打开连接。2.建立一个命令对象。
3.执行插入。核心代码如下:
DataManage DM = new DataManage();    //操作数据库的类
string ConStr = DM.constring();        //获取连接字符串以创建连接
OleDbConnection con = new OleDbConnection(ConStr);    //创建连接
con.Open();                                    //打开连接
string sql = "insert into t_ccnuqikan(news_title, news _publisher, news _datetime, news _content) values('" + title + "','" + txtpublisher + "','" + publishtime + "','" + content + "')";
OleDbCommand cmd = new OleDbCommand(sql, con);        //创建命令对象
cmd.ExecuteNonQuery();                            //执行插入
cmd.Dispose();                                //释放资源
con.Close();                                    //关闭连接
    通过上面的代码我们就可以实现插入了,看起来似乎很简单,无非是再添加一些判断语句和获取用户输入的内容,以及发布成功后弹出一个提示。问题似乎就是这么简单,对不对?
二、初步思考
    但是事实证明后来发布新闻时却出现了问题,当我把一个Word文档里的内容粘贴上去发布时却不能响应,查看数据库发现也没有增加记录,究竟是什么原因呢?
猜想1:我把新闻内容存在一个string类型的字符串里,是不是字符串溢出了?
    测试:我用Response.Write输出这个变量的值,发现和文档里的一模一样,说明猜想不成立.
猜想2:是不是数据库溢出了?新闻内容对应的字段是“备注”类型,是不是超过最大容量了?
    测试:查询相关资料,发现备注类型最大可容量65535个字符,而我的新闻是8064个字符,远没有达到最大容量。说明不会是异常导致的。
猜想3:是不是内容溢出导致的?
    推理:我的电脑的内存是2G,如果内存溢出,那么电脑肯定很卡,但从任务管理器看,发现内存还有很大空闲。
    到此,我已经不出更好的理由了,我用其它文件都测试了,发现都可以上传,可是这个文件就是不行,这让我对这个文件展开了研究。
三、深入分析
    我先把这篇新闻的部分内容上传来测试,发现可以上传,我就用这种方法来做无聊的测试,最终测试出来竟然是一个单词“china’s”引起,我简直难以置信!一个单词竟然引发数据库插入异常,我又把这个单词输入进去测试,发现还是不能上传,那么这个单词有什么特点呢?
    经过分析,我发现这个单词带有一个逗号,或者说英文输入法下的单引号,我测试了一下类似的单词,发现果然结果一样。原来这就是问题之所在。
四、进一步思考及解决
    之前,系网站后台也出现过这种问题,我弄了一上午也没有解决,今天终于到原因了,但为什么会这样呢?
    我立刻想到了SQL语句的构造,许多黑客通过登录入口输入特殊的字符构造SQL语句进行查询从而绕过验证入侵后台,而这里也是一样。
    举个例子:用户名控件的IDtxtUserName,    密码控件的IDtxtPwd,定义两个string变量usernamepassword来存储他们的值,当用户输入用户名和密码的时候,通过这两个控件获取他们的值,然后保存在这两个变量中,通过这两个变量来构造SQL查询语句,这里的SQL查询语句如下:
string sql=”select * from t_user where t_uname=’”+username+”’ and t_upwd=’”+password+”’”;
    对于一般的用户来说,他输入的字符没有特殊字符,比如一个用户输入的用户名为test,密码为test,则构造的SQL语句为:
string sql=”select * from t_user where t_uname=test and t_upwd=test”;
对于这个语句,用SQL语法分析很显然没有什么问题,但对于黑客用户,他如果在用户名和密码里分别输入test’ or ‘1’=’1,我们来看一下构造的SQL语句将为成为:
string sql=”select * from t_user where t_uname=test or 1=1 and t_uname=test or 1=1”
显然,这个语句执行的结果肯定为真,那么黑客就很容易通过验证进入后台。而我之前出现的异常也是同样的原因导致构造的SQL语句不合法所致。
    黑客入侵网站的方式很多,如SQL注入式攻击、数据库破解、上传漏洞攻击等等,而这些问题中很多都与SQL语句的构造有关,怎么解决这类问题呢?
    我们来看另外一种执行查询操作的写法:
OleDbConnection conn = new OleDbConnection(conStr);
conn.Open();
string sqlQuery = "select * from t_user where t_name=@u_Name and t_password=@u_Pwd";
OleDbCommand cmd = new OleDbCommand(sqlQuery, conn);
cmd.Parameters.AddWithValue("@u_Name", txtUserName);
cmd.Parameters.AddWithValue("@u_Pwd", txtPassword);
通过这种方式的参数映射,实现的查询可以避免黑客的攻击,也可以避免引发数据库异常。同样,前面提到的插入也可以采用这种方法实现。当然,对于一些常见的攻击的处理,如果要做到更好地阻止,还需要对用户输入的字符进行过滤,目前防止SQL注入式攻击常常采用这种方法并且效果还不错。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。