【问题标题】:how to use c# variables in sql commands如何在sql命令中使用c#变量
【发布时间】:2014-11-28 17:01:09
【问题描述】:

这是我想用的;

string insertQuery = @"insert into userinfo (UserName, FirstName, LastName, 
                      E-mail, Password,  Country) 
                      values ( '" + uname + "', '" + fname + 
                      "','" + lname + "', '" + email + "')";

其中 + 之间的每个变量都是带有值的字符串变量。但是当我运行这个命令时,我得到了一些不正确的语法错误。

这是我得到的新错误;

errorSystem.Data.SqlClient.SqlException (0x80131904):字符串或二进制 数据将被截断。该语句已终止。在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler、SqlDataReader 数据流、 BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean & dataReady) 在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior,字符串 resetOptionsString) 在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior、RunBehavior runBehavior、布尔 returnStream、布尔 异步,Int32 超时,任务和任务,布尔 asyncWrite,SqlDataReader ds) 在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior、runBehavior、布尔返回流、字符串 方法,TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean asyncWrite) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1 完成,字符串方法名,布尔型 sendToPipe,Int32 超时, 布尔 asyncWrite) 在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 在 Registration.RegistrationPage.Button1_Click1(对象发送者,EventArgs e) 在 c:\Users\kristhnen.jagambrum\Documents\Visual Studio 中 2012\Projects\Registration\Registration\RegistrationPage.aspx.cs:line 50 ClientConnectionId:6d959e49-5b62-43be-b202-76f7eb1fbd2c

【问题讨论】:

  • SQL Injection alert - 你应该NEVER像你提议的那样将你的SQL语句连接在一起; 总是使用参数化查询来避免SQL注入!!
  • 您列出了要插入数据的 6 列,但只有 4 个值。是的,请考虑使用 Parameters 来防止 SQL 注入。
  • 除了@marc_s 所说的,E-mail 列需要转义,因为这是一个表达式,E 减去mail。尝试"E-mail"[E-mail],但是是的,不要连接字符串以形成 sql!
  • 首先要注意上述警告,但在短期内,您可以调试代码并查看分配给insertQuery的值
  • I get some incorrect syntax error 根本不是很有用的信息。为什么不将错误文本复制并粘贴到您的帖子中?

标签: c# sql variables


【解决方案1】:

您问得很好 - 您展示的代码在一行中完美地说明了两个安全问题:

  • 表结构说明了黑客窃取用户密码的原因。
  • C# 代码使 SQL 注入攻击成为可能。

解决第一个问题很难:您需要了解密码哈希以及如何将用户信息存储在数据库中。这是一个可以帮助您的问答:Best way to store passwords in DB

第二个问题更简单——你只需要用参数名称替换注入的值,然后为每个参数名称添加值:

... // Create SQL command, then set its text
command.CommandTest = @"INSERT INTO userinfo (
    UserName, FirstName, LastName, E-mail, Password_hash, Password_salt, Country
) VALUES ( @uname, @fname, @lname, @email, @pwd_hash, @pwd_salt, @country)";
// Bind the parameters
command.Parameters.Add(new SqlParameter("@uname", uname));
command.Parameters.Add(new SqlParameter("@fname", fname));
... // ...and so on
command.ExecuteNonQuery();

【讨论】:

    【解决方案2】:

    答案是你不这样做,因为这是一个坏主意。你应该改用SQlCommand

    Check This out,并且有很多如何使用它的例子。以你的方式追加变量被认为是25 most dangerous programming mistakes. 列表中的错误号3

    【讨论】:

      【解决方案3】:

      试试这样,不要在sql命令中使用直接参数

      public const string InsertStmtUsersTable = "insert into userinfo (UserName, FirstName, LastName, 
                            [E-mail], Password,  Country) values (@UserName, @FirstName, @LastName, 
                            @[E-mail], @Password,  @Country) "
          using(SqlConnection conn = new SqlConnection(connString))
          {
              conn.Open();
      
              using (SqlCommand command = new SqlCommand(InsertStmtUsersTable, conn))
              {
                 command.CommandType = CommandType.Text;
      
                 command.Parameters.Add(new SqlParameter("username", userNameString));
                 command.Parameters.Add(new SqlParameter("FirstName", FirstNameString));
                 // Rest of your Parameters here
      
                 command.ExecuteNonQuery();
              }
          }
      

      【讨论】:

      • 1. SqlCommand 也是一次性的,将其包裹在 using 中。 2. 而不是Parameters.Add(new SqlParameter(...)),你可以使用Parameters.AddWithValue()
      • @JeroenMostert:您应该查看Can we stop using AddWithValue() already? 并小心使用.AddWithValue() - 它可能会导致意想不到和令人惊讶的结果...
      • @JeroenMostert:有多种方法可以做任何事情,这只是示例代码,所以 OP 有一些想法,如何做到这一点
      • @marc_s:谢谢你,我一直在想它,但找不到页面。请注意,在这种情况下,new SqlParameter() 省略了类型,所以它肯定没有更好
      • 感谢@marc_s,注意拼写错误,使用using
      猜你喜欢
      • 2018-09-29
      • 2011-07-31
      • 1970-01-01
      • 2011-10-28
      • 1970-01-01
      • 2022-01-08
      • 2015-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多