Windows Phone 7手机开发、
.Net培训、期待与您交流! 1、参数化查询
前面使用的查询语句可能会引起sql注入攻击,所谓sql注入攻击,就是用户在输入数据时构造一条sql语句,让查询顺利进行,取消了任何验证逻辑。我们拿登陆程序来试验下。
对于一个登陆模块,通常我们要求用户输入用户名和密码,然后提交到数据库进行验证,
我们假设用户名 为admin 密码为 888888
登陆界面 txtUserName文本框是用户名,passwordBox是用户密码。
当我们输入用户名和密码时,普通情况下我们是通过构造一个查询字符串提交到数据库来验证是否匹配
string userName = txtUserName.Text; //取得用户输入的用户名
string password = passwordBox.Password; //取得用户输入与的密码
using ( SqlConnection conn = new SqlConnection ( "Data Source=.;Initial Catalog=test;User ID=sa;Password=123456" ) )//创建连接对象
{
conn.Open ( ); //打开连接对象
using ( SqlCommand cmd = new SqlCommand ( ) )//创建命令对象
{
cmd.CommandText = "select count(*) from T_user where name = " + "'"+userName+ "'" +"and password =" + "'"+password+"'"; //构造sql语句
cmd.Connection = conn;
{
MessageBox.Show ( "登陆成功" );
}
else
{
MessageBox.Show ( "登陆失败" );
}
}
}
这样,当我们输入正确的用户名和密码时,会提示和登陆正确 ,但是我们来看我们的sql语句
select count(*) from T_user where name = " + "'"+userName+ "'" +"and password =" + "'"+password+"'"
当我们在用户名中输入admin时,在密码框中输入以下字符串1 ' or '1'='1 看看我们构造出来的语句是什么
select count(*) from T_user where name = ‘admin' and password = '1' or '1'='1'
这个sql语句一定是成功的,因为'1'='1'始终是成立的,这样,我们通过一些特殊的输入通过了密码的验证。这就是sql注入攻击。
解决这个问题,我们就需要使用参数化查询
string userName = txtUserName.Text;
string password = passwordBox.Password;
using ( SqlConnection conn = new SqlConnection ( "Data Source=.;Initial Catalog=test;User ID=sa;Password=123456" ) )
{
conn.Open ( );
using ( SqlCommand cmd = new SqlCommand ( ) )
{
cmd.CommandText = "select count(*) from T_user where name = @un and password = @ps";
cmd.Parameters.Add(new SqlParameter("@un",userName));
cmd.Parameters.Add(new SqlParameter("@ps",password));
cmd.Connection = conn;
if ( (int)cmd.ExecuteScalar ( ) != 0 )
{
MessageBox.Show ( "登陆成功" );
}
else
{
MessageBox.Show ( "登陆失败" );
}
}
}
看看我们的sql语句,我们使用了@un 和@ps两个参数来代替大量的字符串连接,@表示这是一个参数
cmd.Parameters.Add(new SqlParameter("@un",userName));
cmd.Parameters.Add(new SqlParameter("@ps",password));
这两条语句用来给参数赋值,new SqlParameter("@un",userName) 这个构造函数的第一个参数指定参数名称,注意,这个名称一定要和我们的sql语句中的参数名称相对应,第二个参数就是我们要给参数的值,
这样即使我们使用 1 ' or '1'='1这样的密码,也不能通过验证,
从上面的例子可以看出,sql注入攻击的本质是通过引号之间的就近配对来修改我们的sql语句的结构,灵活的使用''和and or等逻辑字符,构造出一个总能成功执行的sql语句。参数化查询则避免了这种情况。
另外,参数化查询的语句结构也更容易让人看明白,出错后也较容易调试,而字符串拼接出错后不容易调试,也容易出错,所以建议使用参数化查询。 Windows Phone 7手机开发、 .Net培训、期待与您交流!
前面使用的查询语句可能会引起sql注入攻击,所谓sql注入攻击,就是用户在输入数据时构造一条sql语句,让查询顺利进行,取消了任何验证逻辑。我们拿登陆程序来试验下。
对于一个登陆模块,通常我们要求用户输入用户名和密码,然后提交到数据库进行验证,
我们假设用户名 为admin 密码为 888888
登陆界面 txtUserName文本框是用户名,passwordBox是用户密码。
当我们输入用户名和密码时,普通情况下我们是通过构造一个查询字符串提交到数据库来验证是否匹配
string userName = txtUserName.Text; //取得用户输入的用户名
string password = passwordBox.Password; //取得用户输入与的密码
using ( SqlConnection conn = new SqlConnection ( "Data Source=.;Initial Catalog=test;User ID=sa;Password=123456" ) )//创建连接对象
{
conn.Open ( ); //打开连接对象
using ( SqlCommand cmd = new SqlCommand ( ) )//创建命令对象
{
cmd.CommandText = "select count(*) from T_user where name = " + "'"+userName+ "'" +"and password =" + "'"+password+"'"; //构造sql语句
cmd.Connection = conn;
{
MessageBox.Show ( "登陆成功" );
}
else
{
MessageBox.Show ( "登陆失败" );
}
}
}
这样,当我们输入正确的用户名和密码时,会提示和登陆正确 ,但是我们来看我们的sql语句
select count(*) from T_user where name = " + "'"+userName+ "'" +"and password =" + "'"+password+"'"
当我们在用户名中输入admin时,在密码框中输入以下字符串1 ' or '1'='1 看看我们构造出来的语句是什么
select count(*) from T_user where name = ‘admin' and password = '1' or '1'='1'
这个sql语句一定是成功的,因为'1'='1'始终是成立的,这样,我们通过一些特殊的输入通过了密码的验证。这就是sql注入攻击。
解决这个问题,我们就需要使用参数化查询
string userName = txtUserName.Text;
string password = passwordBox.Password;
using ( SqlConnection conn = new SqlConnection ( "Data Source=.;Initial Catalog=test;User ID=sa;Password=123456" ) )
{
conn.Open ( );
using ( SqlCommand cmd = new SqlCommand ( ) )
{
cmd.CommandText = "select count(*) from T_user where name = @un and password = @ps";
cmd.Parameters.Add(new SqlParameter("@un",userName));
cmd.Parameters.Add(new SqlParameter("@ps",password));
cmd.Connection = conn;
if ( (int)cmd.ExecuteScalar ( ) != 0 )
{
MessageBox.Show ( "登陆成功" );
}
else
{
MessageBox.Show ( "登陆失败" );
}
}
}
看看我们的sql语句,我们使用了@un 和@ps两个参数来代替大量的字符串连接,@表示这是一个参数
cmd.Parameters.Add(new SqlParameter("@un",userName));
cmd.Parameters.Add(new SqlParameter("@ps",password));
这两条语句用来给参数赋值,new SqlParameter("@un",userName) 这个构造函数的第一个参数指定参数名称,注意,这个名称一定要和我们的sql语句中的参数名称相对应,第二个参数就是我们要给参数的值,
这样即使我们使用 1 ' or '1'='1这样的密码,也不能通过验证,
从上面的例子可以看出,sql注入攻击的本质是通过引号之间的就近配对来修改我们的sql语句的结构,灵活的使用''和and or等逻辑字符,构造出一个总能成功执行的sql语句。参数化查询则避免了这种情况。
另外,参数化查询的语句结构也更容易让人看明白,出错后也较容易调试,而字符串拼接出错后不容易调试,也容易出错,所以建议使用参数化查询。 Windows Phone 7手机开发、 .Net培训、期待与您交流!