【问题标题】:SQL query execution difficultySQL查询执行难度
【发布时间】:2016-10-29 05:32:33
【问题描述】:

我正在从应用程序添加学生时进行验证。如果我运行以下查询

SELECT ID FROM Student WHERE Name =' " '+str+' " '

会产生如下错误:

列名“str”无效。

我的应用程序将生成 DBException。

我该如何解决这个问题?

编辑

String SName=txtBox1.Text;

String sql="select id from student where name = ' "+SName.Trim()+" ' ";

SqlConnection connection = null;
SqlDataReader reader = null;
try
{
    connection = GetConnection();
    SqlCommand command = new SqlCommand(sql, connection);
    if (_sqltransection != null)
    {
        command.Transaction = _sqltransection;
    }
    reader = command.ExecuteReader(CommandBehavior.CloseConnection);
}            
catch (SqlException ex)
{
    throw new DBException(ex);
}

在哪里txtBox.Text=" '+str+' "

【问题讨论】:

  • 您需要添加更多的单引号使其成为字符串,否则它将被解析为SELECT ID FROM Student WHERE Name =divyesh
  • 加上你的代码看起来很容易被sql注入
  • 什么是 divyesh?它是列名、变量/参数还是(失败的)字符串文字?
  • 为什么需要双引号。您甚至可以在不嵌入双引号的情况下运行它。
  • 在我的应用程序中,如果用户在文本框中输入类似“' +divyesh+'”的字符串,那么我该如何添加更多单引号?.

标签: c# sql asp.net sql-server-2008 ado.net


【解决方案1】:

真的,您正在向您的 dbms 发送此查询

SELECT ID FROM Student WHERE Name ='' divyesh '' 

您的 dbms 可以正确解释 sql 到

SELECT ID FROM Student WHERE Name ='' 

然后找到

divyesh ''

它首先尝试知道 divyesh 它是否是 Student 表的一列,因为它不会引发错误,你会在应用程序异常中看到......

要更正此错误,您应该在应用中的动态查询中将作为过滤器传递的字符串双引号:

SELECT ID FROM Student WHERE Name =' "''+str+''" '

通常,在编写动态查询时,您的情况会被阻止,将“str”过滤器参数提交给某个辅助方法,该方法检查是否存在某些单引号并最终将它们加倍。

对于所说的内容,这是一个(C# 或 Java)微不足道的解决方案:

"SELECT ID FROM Student WHERE Name ='" + str.Replace("'", "''") + "' "


但是我发现在数据库中很难将“名称”字段存储在单引号之间,所以我想知道您打算做什么..

不管你在做什么,在过滤字段中使用单引号,它也是sql注入攻击的一个元素。.

您应该绝对避免这种动态查询,并在您的代码中使用一些基于带有参数的 sql 查询语句的对象模型的 api,然后将输入过滤器传递给“包含”您的查询的对象,实例化参数对象。



在采购订单中澄清后更新

String SName = null;

if(!string.IsNullOrEmpty(txtBox1.Text))    
     SName = txtBox1.Text.trim();


String sql="select id from student where name = @paramName";

SqlConnection connection = null;
SqlDataReader reader = null;
try
{
    connection = GetConnection();
    SqlCommand command = new SqlCommand(sql, connection);

    SqlParameter param = new SqlParameter("@paramName", SqlDbType.NVarChar, 50);
    param.Value = SName ?? SqlString.Null;
    command .Parameters.Add(param);

    if (_sqltransection != null)
    {
        command.Transaction = _sqltransection;
    }
    reader = command.ExecuteReader(CommandBehavior.CloseConnection);
}            
catch (SqlException ex)
{
    throw new DBException(ex);
}

请注意,SqlDbType.NVarChar, 50 指的是您的数据库字段“名称”的数据类型(我想是一个 varchar),因此它的类型和长度应该相等(对于“名称”字段应该去50个字符),无论如何,参数输入过滤器的长度越低越好

【讨论】:

  • 在我的应用程序中,如果用户在文本框中输入类似“'+str+'”的字符串,我该怎么办?
【解决方案2】:

我同意之前的回答。在这种情况下,您必须使用Prepared Statements。 在this 页面您可以找到示例

【讨论】:

  • @Andrew_Bogdanov 欢迎来到 Stack Overflow。我想指出,“以前的”答案可能会被删除或选择为已接受的答案,从而冒泡。如果您想引用特定答案,请使用带有作者姓名的 @ 表示法。一旦您获得足够的声誉,您就可以让 cmets 对特定答案进行改进。使用单个链接回答也不是一个好习惯,因为该链接可能会失效。干杯
  • @RuslanBes 感谢您的来信。 @ 符号怎么样,这对我来说是非常有用的信息。如果我的答案中的链接被破坏,任何读者都可以使用谷歌搜索“Prepared Statement”并找到所有信息。
【解决方案3】:

首先,您的查询结果无效,因为双引号用于数据库对象名称,而不是字符串文字:"divyesh" 是列名,'divyesh' 是字符串。您需要第二个,所以将双引号改为单引号。

其次,永远不要使用用户输入来构造这样的 SQL 语句。如果你的用户选择了一个名字"'; DROP DATABASE yourdb; SELECT '",你的数据库就消失了。阅读有关“SQL 注入”主题的更多信息。

【讨论】:

  • 绝对正确,SQL 注入
【解决方案4】:
SELECT ID FROM Student WHERE Name =' " '+'divyesh'+' " '

但是没有意义……

也许你会喜欢这样的东西:

SELECT ID FROM Student WHERE Name like '%divyesh%'

如果要在字符串中添加单个 cuotes:

SELECT '''hello'''

【讨论】:

  • 但是如何修改用户输入?
  • "从学生姓名中选择 ID = '" + txtStudentName.Text.Trim() + "'"
  • 我知道这没有任何意义,但在我的应用程序中,如果用户输入类似“'+str+'”这样的字符串,那我该怎么办?
  • 为了更清楚,"SELECT ID FROM Student WHERE Name = ' " + txtStudentName.Text.Trim() + " ' "
  • "SELECT ID FROM Student WHERE Name = ' " + txtStudentName.Text.Trim() + " not working 产生同样的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
相关资源
最近更新 更多