之前实现的用户登录窗体,我们在用户名和密码框中都输入1‘ or ‘1’=1’,如下图所示。单击“登录“按钮后,你会发现竟然也能进入主窗体!我们输入的名户名和密码并不正确,为何也能进入系统呢?
登录成功后,显示的主窗体,如下图:
这就涉及到了“SQL注入攻击”问题。我们在程序中存在着大量拼接产生SQL语句的代码,这就会导致一个比较大的安全隐患,容易遭受SQL注入攻击。就这个窗体例子来说,我们在代码中用的SQL语句是:
string sqlStr = "select * from [Users] where UserName='" + txtUserName.Text.Trim()
+ "'and Password='" + txtUserPassword.Text.Trim() + "'";
在用户名、密码框中输入1‘ or ‘1’=1’后产生的SQL语句为:
select * from [Users] where UserName='1' or '1'='1' and Password='1' or '1'='1
而‘1’=‘1’永远是正确的。这样,用户在不知道合法的用户名和密码的情况下,通过构造特殊的SQL语句,就顺利地进入了系统,导致我们的用户验证模块形同虚设!为了避免这种情况的发生,提高程序的安全性,需要使用参数化SQL语句。
在ADO.NET对象模型中执行一个参数化查询,需要向SqlCommand对象的Parameters集合添加SqlParameter对象。生成SqlParameter对象最简单的方式是调用SqlCommand对象的Parameters集合的AddWithValue方法。
这里又学习了一个新的对象:SqlParameter,表示SqlCommand的参数。
使用参数化SQL语句的步骤是:
- 定义包含参数的SQL语句,用@符号声明参数。
- 为SQL语句中出现的每一个参数定义参数对象,并将参数对象加入到SqlCommand对象中。
- 给参数赋值,并执行SQL语句。
所以,修改上面的代码为:
string sqlStr="select * from [Users] where UserName=@UserName and Password=@Password"
然后创建命令对象的代码时,修改为:
现在,再次运行程序,在用户名和密码框中都输入‘1 or ’1‘=1’后,会提示“用户名或密码错误”,这样用户就没有办法非法登录系统了。