2010-08-13 95 views
9

谷歌变成了各种各样的消毒Web访问查询的讨论,但我没有找到任何解决什么,我关心的是:在C#程序消毒SQL数据

消毒用户输入数据。这必须通过可逆转化来完成,而不是通过去除。作为问题的一个简单例子,我不想破坏爱尔兰人的名字。

什么是最好的方法,是否有任何库函数呢?

+7

是否将可能包含撇号的数据传递给SQL查询?如果您使用SQL Parameter对象,那应该不成问题。你会得到你的消毒,并且你的数据中的任何重要字符都应该被正确地转义。 – 2010-08-13 17:53:02

+0

同意的参数化查询是可行的方法。 – driis 2010-08-13 17:57:53

+0

我只通过业务逻辑生成SQL查询。 – Jeroen 2010-08-13 18:11:45

回答

9

这取决于您使用的SQL数据库。例如,如果你想在MySQL中使用单引号,你需要使用一个反斜杠Dangerous:'和一个逃脱的转义字符:\'。对于MS-SQL,情况完全不同,危险:'转义:''。当您以这种方式转义数据时,不会删除任何内容,它是一种表示控制字符的方式,如字面形式的引号。

下面是使用MS-SQL和C#参数化查询,从Docs采取的一个例子:

private static void UpdateDemographics(Int32 customerID, 
    string demoXml, string connectionString) 
{ 
    // Update the demographics for a store, which is stored 
    // in an xml column. 
    string commandText = "UPDATE Sales.Store SET Demographics = @demographics " 
     + "WHERE CustomerID = @ID;"; 

    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     SqlCommand command = new SqlCommand(commandText, connection); 
     command.Parameters.Add("@ID", SqlDbType.Int); 
     command.Parameters["@ID"].Value = customerID; 

     // Use AddWithValue to assign Demographics. 
     // SQL Server will implicitly convert strings into XML. 
     command.Parameters.AddWithValue("@demographics", demoXml); 

     try 
     { 
      connection.Open(); 
      Int32 rowsAffected = command.ExecuteNonQuery(); 
      Console.WriteLine("RowsAffected: {0}", rowsAffected); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 
} 

对于MySQL我不知道,你可以使用参数化查询库。您应该使用mysql_real_escape_string()或者任意使用此功能。:

public static string MySqlEscape(this string usString) 
{ 
    if (usString == null) 
    { 
     return null; 
    } 
    // SQL Encoding for MySQL Recommended here: 
    // http://au.php.net/manual/en/function.mysql-real-escape-string.php 
    // it escapes \r, \n, \x00, \x1a, baskslash, single quotes, and double quotes 
    return Regex.Replace(usString, @"[\r\n\x00\x1a\\'""]", @"\$0"); 
} 
+1

我意识到这是一个较旧的帖子,但PHP [5.0 +]确实通过MySQLi(http://php.net/manual/en/book.mysqli.php)和PDO库(http:///php.net/manual/en/book.pdo.php)。 – 2012-06-19 09:52:06

+0

@Tieson T.和adodb,以及参数化查询是最好的选择。 – rook 2012-06-19 17:42:13

+1

fyi,mysql_real_escape_string已被弃用 – 2013-04-22 18:29:36

0

使用适当构造的DAL与SQL参数对象交给存储过程,您不必担心这一点。实现业务对象和dal以足够抽象用户输入,以使其不作为SQL执行,而是作为值进行识别。示例很有趣:

public class SomeDal 
{ 
    public void CreateUser(User userToBeCreated) 
    { 
     using(connection bla bla) 
     { 
      // create and execute a command object filling its parameters with data from the User object 
     } 
    } 
} 

public class User 
{ 
    public string Name { get; set; } 
    ... 
} 

public class UserBL 
{ 
    public CreateUser(User userToBeCreated) 
    { 
     SomeDal myDal = new SomeDal(); 
     myDal.CreateUser(userToBeCreated); 
    } 
} 

public class SomeUI 
{ 
    public void HandleCreateClick(object sender, e ButtonClickEventArgs) 
    { 
     User userToBeCreated = new User() { Name = txtName.Text }; 
     UserBL userBl = new UserBL(); 
     userBl.CreateUser(userToBeCreated); 
    } 
} 
+0

我看到parematerized命令是要走的路,但您的示例代码与它们无关! – 2010-08-13 20:26:33

+0

@Loren Pechtel:评论说要使用它们,而且你希望你的用户输入填充一个像User的业务对象,它充当传输到dal的业务对象,它创建命令和参数。这种抽象将数据库中的用户与安全性分离,因为你可以创建一个UserValidator和其他类似的东西,使得他们的输入不仅可以从SQL注入中安全使用,而且可以避免无效值。 – 2010-08-13 20:31:34

+0

我同意你需要一个检查有效性的层次,但这与保持系统免于奥尼尔先生的窒息是分开的。 – 2010-08-14 04:51:36