防止SQL注入攻击。
代码1-1
private void cmdLogin_Click(object sender, System.EventArgs e) {
string strCnx =
"server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
//This code is susceptible to SQL injection attacks.
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser.Text + "' AND Password='" + txtPassword.Text + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int) cmd.ExecuteScalar();
if (intRecs>0) {
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, false);
}
else {
lblMsg.Text = "Login attempt failed.";
}
cnx.Close();
}
private void cmdLogin_Click(object sender, System.EventArgs e) {
string strCnx =
"server=localhost;database=northwind;uid=sa;pwd=;";
SqlConnection cnx = new SqlConnection(strCnx);
cnx.Open();
//This code is susceptible to SQL injection attacks.
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser.Text + "' AND Password='" + txtPassword.Text + "'";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
intRecs = (int) cmd.ExecuteScalar();
if (intRecs>0) {
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, false);
}
else {
lblMsg.Text = "Login attempt failed.";
}
cnx.Close();
}
上面这段代码容易被SQL注入攻击成功。
看一下查询语句:
string strQry = "SELECT Count(*) FROM Users WHERE UserName='" +
txtUser.Text + "' AND Password='" + txtPassword.Text + "'";
如果是正常的用户登录则查询语句会是如下这种形式:
SELECT Count(*) FROM Users WHERE UserName='Paul' AND Password='password'
但是,如果有人输入的用户名是 ' Or 1=1 – 则查询语句就变成了:
SELECT Count(*) FROM Users WHERE UserName='' Or 1=1
这样的话 1=1 地球都知道这结果是True
如何防范?
把代码1-1写成代码1-2(推荐)或1-3的形式,看看就明白其中的道理了。
//代码1-2存储过程参数(强烈推荐使用存储过程)
private void cmdLogin_Click(object sender, System.EventArgs e) {
string strCnx =
ConfigurationSettings.AppSettings["cnxNWindBetter"];
using (SqlConnection cnx = new SqlConnection(strCnx))
{
SqlParameter prm;
cnx.Open();
string strAccessLevel;
SqlCommand cmd = new SqlCommand("procVerifyUser", cnx);
cmd.CommandType= CommandType.StoredProcedure;
prm = new SqlParameter("@username",SqlDbType.VarChar,50);
prm.Direction=ParameterDirection.Input;
prm.Value = txtUser.Text;
cmd.Parameters.Add(prm);
prm = new SqlParameter("@password",SqlDbType.VarChar,50);
prm.Direction=ParameterDirection.Input;
prm.Value = txtPassword.Text;
cmd.Parameters.Add(prm);
strAccessLevel = (string) cmd.ExecuteScalar();
if (strAccessLevel.Length>0) {
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, false);
}
else {
lblMsg.Text = "Login attempt failed.";
}
}
}
//代码1-3 命令参数
private void cmdLogin_Click(object sender, System.EventArgs e) {
string strCnx = ConfigurationSettings.AppSettings["cnxNWindBad"];
using (SqlConnection cnx = new SqlConnection(strCnx))
{
SqlParameter prm;
cnx.Open();
string strQry =
"SELECT Count(*) FROM Users WHERE UserName=@username " +
"AND Password=@password";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
cmd.CommandType= CommandType.Text;
prm = new SqlParameter("@username",SqlDbType.VarChar,50);
prm.Direction=ParameterDirection.Input;
prm.Value = txtUser.Text;
cmd.Parameters.Add(prm);
prm = new SqlParameter("@password",SqlDbType.VarChar,50);
prm.Direction=ParameterDirection.Input;
prm.Value = txtPassword.Text;
cmd.Parameters.Add(prm);
intRecs = (int) cmd.ExecuteScalar();
if (intRecs>0) {
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, false);
}
else {
lblMsg.Text = "Login attempt failed.";
}
}
}
private void cmdLogin_Click(object sender, System.EventArgs e) {
string strCnx =
ConfigurationSettings.AppSettings["cnxNWindBetter"];
using (SqlConnection cnx = new SqlConnection(strCnx))
{
SqlParameter prm;
cnx.Open();
string strAccessLevel;
SqlCommand cmd = new SqlCommand("procVerifyUser", cnx);
cmd.CommandType= CommandType.StoredProcedure;
prm = new SqlParameter("@username",SqlDbType.VarChar,50);
prm.Direction=ParameterDirection.Input;
prm.Value = txtUser.Text;
cmd.Parameters.Add(prm);
prm = new SqlParameter("@password",SqlDbType.VarChar,50);
prm.Direction=ParameterDirection.Input;
prm.Value = txtPassword.Text;
cmd.Parameters.Add(prm);
strAccessLevel = (string) cmd.ExecuteScalar();
if (strAccessLevel.Length>0) {
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, false);
}
else {
lblMsg.Text = "Login attempt failed.";
}
}
}
//代码1-3 命令参数
private void cmdLogin_Click(object sender, System.EventArgs e) {
string strCnx = ConfigurationSettings.AppSettings["cnxNWindBad"];
using (SqlConnection cnx = new SqlConnection(strCnx))
{
SqlParameter prm;
cnx.Open();
string strQry =
"SELECT Count(*) FROM Users WHERE UserName=@username " +
"AND Password=@password";
int intRecs;
SqlCommand cmd = new SqlCommand(strQry, cnx);
cmd.CommandType= CommandType.Text;
prm = new SqlParameter("@username",SqlDbType.VarChar,50);
prm.Direction=ParameterDirection.Input;
prm.Value = txtUser.Text;
cmd.Parameters.Add(prm);
prm = new SqlParameter("@password",SqlDbType.VarChar,50);
prm.Direction=ParameterDirection.Input;
prm.Value = txtPassword.Text;
cmd.Parameters.Add(prm);
intRecs = (int) cmd.ExecuteScalar();
if (intRecs>0) {
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, false);
}
else {
lblMsg.Text = "Login attempt failed.";
}
}
}