0

我有以下身份验证方法:

protected void Button1_Click(object sender, EventArgs e)
        {            
            string s;
            s = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            SqlConnection con = new SqlConnection(s);
            con.Open();
            string sqlCmd;
            sqlCmd = "SELECT Username, UserPassword FROM Benutzer WHERE Username = @Username AND UserPassword =@Password";
            SqlCommand cmd = new SqlCommand(sqlCmd, con);
            String username = tbUsername.Text.Replace("'", "''");
            String password = tbPassword.Text.Replace("'", "''");
            cmd.Parameters.AddWithValue("Username", username);
            cmd.Parameters.AddWithValue("Password", password);
            string CurrentName;
            CurrentName = (string)cmd.ExecuteScalar();
            if (CurrentName != null)
            {
                Session["UserAuthentication"] = cmd.Parameters[0].ToString();
                Session.Timeout = 1;
                Response.Redirect("Default.aspx");
            }
            else
            {
                lblStatus.ForeColor = System.Drawing.Color.Red;
                lblStatus.Text = "Benuztername/Password ungültig!";
            }
        }

这足以防止sql注入吗?我以前只是将用户名和密码直接输入到命令中,如下所示:

sqlCmd = "SELECT Username, UserPassword FROM Benutzer WHERE Username ='" + username + "' AND UserPassword ='" + pwd + "'";

其中 username 和 pwd 仅在其中存储用户名和密码文本框内容的字符串变量...

编辑:

好的,我已经编辑了我的代码,现在看起来像这样:

protected void Button1_Click(object sender, EventArgs e)
        {
            SqlConnection objcon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
            SqlDataAdapter objda = new SqlDataAdapter("[MembershipPruefen]", objcon);
            objda.SelectCommand.CommandType = CommandType.StoredProcedure;
            objda.SelectCommand.Parameters.Add("@Username", SqlDbType.VarChar).Value = tbUsername.Text;
            objda.SelectCommand.Parameters.Add("@UserPassword", SqlDbType.VarChar).Value = tbPassword.Text;
            objcon.Open();
            string CurrentName;
            CurrentName = (string)objda.SelectCommand.ExecuteScalar();
            if (CurrentName != null)
            {
                Session["UserAuthentication"] = tbUsername.Text;
                Session.Timeout = 1;
                Response.Redirect("Default.aspx");
            }
            else
            {
                lblStatus.ForeColor = System.Drawing.Color.Red;
                lblStatus.Text = "Benuztername/Password ungültig!";
            }
            objcon.Close();            
        }

这是我的存储过程:

CREATE PROCEDURE MembershipPruefen (@Username VARCHAR(50), @UserPassword VARCHAR(50))  
AS 

SELECT Username, UserPassword FROM Benutzer WHERE Username LIKE @Username AND UserPassword LIKE @UserPassword; 

这足够了吗?我的 Web 应用程序会不会受到 sql 感染的影响,或者还有什么事情要做吗?

4

4 回答 4

2

使用存储过程并且只返回一个值来表示它存在于数据库中(即行计数),或者如果您需要将用户名用于会话数据等,则只需返回用户名。

这向用户显示的数据库数据更少:)

有关存储过程的信息:http: //support.microsoft.com/kb/306574

于 2013-03-12T14:15:54.520 回答
2

我会创建一个专用的 sql server 用户来连接到数据库(我猜你现在正在连接 ths 'sa'?)。

这意味着您向数据库添加了一个完全没有权限的新用户,当您第一次运行应用程序时,您会得到一个 sql 异常,如预期的那样,您没有读取权限。您为新创建的用户授予对“Benutzer”表的 SELECT 权限,依此类推。

当您这样做时,即使您的连接受到威胁,攻击者也无法执行系统存储过程等。

一件额外的事情:建议您对密码进行哈希处理,因此您的密码永远不会被真实文本读取。这是一篇很大的文章,我看到你没有太多时间,但我强烈建议你实现散列密码。 http://crackstation.net/hashing-security.htm

编辑:我LIKE在您的存储过程中看到一个,我会说=,用户必须输入正确的密码!

我看到您从 sql 语句更改为存储过程:在前面的文本中,将表的 SELECT 权限更改为存储过程的 EXECUTE 权限。

于 2013-03-12T15:12:35.540 回答
2

使用参数化查询(SqlCommand 和 SqlParameter)并将用户输入放入参数中。不要根据未经检查的用户输入构建 SQL 字符串。不要假设您可以构建一个可以检查用户输入的各种格式错误的清理程序。边缘情况很容易被遗忘。检查数字输入可能很简单,可以保证您的安全,但对于字符串输入,只需使用参数。检查二级漏洞 - 如果这些值包含用户输入,则不要从 SQL 表值构建 SQL 查询字符串。使用存储过程来封装数据库操作。

或者使用准备好的语句,这将通过使用 ORM 形成,如 Linq to SQL 或 NHibernate,它们在内部使用准备好的语句。

于 2013-03-12T14:18:39.537 回答
1

使用准备好的语句:

SqlCommand.Prepare

MSDN

于 2013-03-12T14:12:55.477 回答