2015-11-06 36 views
2

在我的ColdFusion 11的应用程序,使用SQL Server 2008 R2,我下面一个CF组件内CFQUERY标签:ColdFusion的单引号问题与SQL查询

<cfquery name="result_set" dataSource="#request.dsn_name#"> 
    select name, state from myTable #REReplace(where_clause,"''","'","ALL")#   
</cfquery> 

这里where_clause是一个变量。 CF用两个单引号替换,因此我使用REReplace函数将两个单引号替换为一。所以我的查询会改变,例如从

select name, state from myTable WHERE name IN (''ABC'') 

这样:

select name, state from myTable WHERE name IN ('ABC') 

问题是,当一个名字列值包含一个单引号为好。例如。

select name, state from myTable WHERE name IN ('Smith's bat') 

在这种情况下查询失败。我该如何解决这些问题。我尝试了PreserveSingleQuotes,但它具有相同的问题,其中列的值使用单引号。

UPDATE

这个程序使用的ColdFusion MX 7原作者是创建基于某些条件where_clause变量动态字符串开发年前由一个人。这是一个很长的cfs文件,有几个条件用于为where_clause创建动态字符串。因此,使用cfqueryparam可能不合适,或者可能需要彻底检查客户不允许的代码。

+5

更好的方法是重写查询以使用参数('')。这样做会非常容易出错,并可能导致[** SQL注入**](https://www.owasp.org/index.php/SQL_Injection)漏洞。 –

+5

...并且是您首先遇到查询问题的原因。不要使用那种动态sql。相反,在cfquery中构建sql并在所有参数上使用cfqueryparam(或者查看使用cfscript查询,这为“参数化”sql提供了更多的灵活性)。这既能保护数据库,又能消除这种类型的错误。 – Leigh

+4

如果你想坚持在''调用之外创建你的SQL字符串,可以使用'queryExecute()'来代替它,它允许你将参数占位符放入SQL字符串中;然后将参数值传递给单独的数组/结构。只是*不要*将值硬编码到SQL字符串中。这是可怕的,尴尬的,危险的。 –

回答

1

这是一个讨厌的问题。恐怕我只能想出一个讨厌的“解决方案”。

  • 替代值分隔符:<cfset where_clause = replace(where_clause, "''", "§§", "ALL")>
  • 然后逃逸的实际单引号:<cfset where_clause = replace(where_clause, "'", "\'", "ALL")>
  • 现在恢复替代和规范分隔符:<cfset where_clause = replace(where_clause, "§§", "'", "ALL")>

一起把它扔:

<cfset substitution = "§§"> <!--- use whatever char sequence works best for your data ---> 

<!--- fallback in case the substitution is part of your data ---> 
<cfif where_clause contains substitution> 

    <cfset substitution = "°°°"> 
    <!--- 
     you can basically start looping through a bunch of alternatives 
     or even expand the substition with an additional character 
     ...you get the idea 
    ---> 

</cfif> 

<cfset where_clause = replace(where_clause, "''", substitution, "ALL")> 
<cfset where_clause = replace(where_clause, "'", "\'", "ALL")> 
<cfset where_clause = replace(where_clause, substitution, "'", "ALL")> 

<cfquery... 

正如你所见,这仍然是高度问题,并可能在一天失败。但只要你必须处理where_clause变量,可能没有更好的选择。

0

您需要使用的功能PreserveSingleQuotes,这种方式:

<cfquery name="result_set" dataSource="#request.dsn_name#"> 
    select name, state from myTable #PreserveSingleQuotes(REReplace(where_clause,"''","'","ALL"))#   
</cfquery> 

有一个好的一天!

+0

@PauloTexeira。您的建议会给出错误信息:'函数PreserveSingleQuotes'不支持复杂结构' – nam

+0

打印字符串的cfdump以帮助我们理解数据。 –

+0

请记住,只有在单引号正确转义的情况下才有效,而不是(从OP中判断)。从个人经验来看,这种动态sql极其容易出错,并且极其痛苦,无法调试...更不用说它将数据库全部公开给sql注入。尽管可以使其工作,但切换到“参数化”查询是更安全和更理想的IMO选项 – Leigh