SQL注入攻击和防范


-------  Windows Phone 7手机开发、 .Net培训、期待与您交流! -------

        大多数网站都有登录功能,用户注册以后凭用户的用户名和密码进行登录,好多人判断登录是否成功是取用户输入的用户名和密码去数据库中查找,如果存在符合条件的记录则认为登录成功。比如一下是一个简单的例子。

static void Main(string[] args)
        {
            Console.WriteLine("请输入用户名!");
            string username = Console.ReadLine();
            Console.WriteLine("请输入密码!");
            string password = Console.ReadLine();

            string sqlstr = "server=.;database=dbname;uid=sa;pwd=sa";
            using (SqlConnection conn = new SqlConnection(sqlstr))
            {
                conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select count(*) from T_userinfo where username='" + username + "' and password='" + password + "'";
                    int c = Convert.ToInt32(cmd.ExecuteScalar());
                    if (c > 0)
                    {
                        Console.WriteLine("登录成功!");
                    }
                    else
                    {
                        Console.WriteLine("登录失败!");
                    }
                    Console.ReadKey();
                }
            }
        }


        但是这样的代码看似没什么问题,实则存在一个严重的安全漏洞,即SQL注入漏洞。比如数据库中我们的用户名是admin,密码是123456,可以通过一种方法在不知道密码的情况下成功登录。输入 1‘ or ’1'='1  即可。



        当然,输入的不一定跟这个一模一样,只要让sql命令的字符串拼起来会有一个true就行了,比如这里的 or ‘1’=‘1 拼起来它就是true,’1‘=’1‘嘛。在程序中设断点监视一下此时的SQL语句拼成了什么样的。

select count(*) from T_userinfo where username='admin' and password='1' or '1'='1'

看到了吧 or ’1'='1',这个是永远成立的,所以这是个很严重的问题。那么怎么解决呢,下面是解决方法,即参数化用户名和密码。代码如下
static void Main(string[] args)
        {
            Console.WriteLine("请输入用户名!");
            string username= Console.ReadLine();
            Console.WriteLine("请输入密码!");
            string password = Console.ReadLine(); 

            string sqlstr = "server=.;database=dbname;uid=sa;pwd=sa";
            using (SqlConnection conn = new SqlConnection(sqlstr))
            {
                conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select count(*) from T_userinfo where username=@uid and password=@pwd";
                    cmd.Parameters.Add(new SqlParameter("uid",username));
                    cmd.Parameters.Add(new SqlParameter("pwd",password));
                    int c = Convert.ToInt32(cmd.ExecuteScalar());
                    if (c > 0)
                    {
                        Console.WriteLine("登录成功!");
                    }
                    else
                    {
                        Console.WriteLine("登录失败!");
                    }
                    Console.ReadKey();
                }
            }
        }


可以看到这一次登录失败了,也就是有效防止了SQL注入的攻击。同样设断点看SQL语句是怎样的

select count(*) from T_userinfo where username=@uid and password=@pwd
这次没有再拼字符串,而是用参数的形式代替,参数通过cmd.Parameters.Add()添加进去。这是SQL Server不是简单的拿字符串去拼接,而是把用户输入的这一串当成一个字符串而不是命令的一部分。


-------  Windows Phone 7手机开发、 .Net培训、期待与您交流! ------  详细请查看: http://net.itheima.com


你可能感兴趣的:(黑马学习日记,sql,string,sql,server,windows,phone,数据库,server)