为什么在这些情况下,ColdFusion哈希函数返回不同的结果?

3
这是我第一次注意到ColdFusion表现出这种行为。我在更新一个查询以使用<cfqueryparam>时遇到了这个问题。该代码运行在ColdFusion 8平台上,我没有参考其在该版本之外的行为的资料。
此外,我们通常会对插入值使用<cfqueryparam>,这也促使我们对这个问题进行调查。
对于这个示例,我们将假设"first_string"和"second_string"包含一些文本,例如来自<textarea>表单发布的标题和带有换行符的一些段落文本。
我们还可以假定"md5_hashed_value"列的SQL数据类型为char(32)。 场景1:
<cfset hashed_value = hash(first_string & second_string, "MD5")>
<cfquery name="my_query" datasource="#my_datasource_name#">
    INSERT INTO my_table
    (
        md5_hashed_value
    )
    VALUES
    (
        '#hashed_value#'
    )
</cfquery>

在第一个场景中,将创建哈希值。 场景2:
<cfquery name="my_query" datasource="#my_datasource_name#">
    INSERT INTO my_table
    (
        md5_hashed_value
    )
    VALUES
    (
        '#hash(first_string & second_string, "MD5")#'
    )
</cfquery>

在第二种情况下,计算出的哈希值与第一种情况不同。 第三种情况
<cfquery name="my_query" datasource="#my_datasource_name#">
    INSERT INTO my_table
    (
        md5_hashed_value
    )
    VALUES
    (
        <cfqueryparam value="#hash(first_string & second_string, "MD5")#" CFSQLType="CF_SQL_CHAR">
    )
</cfquery>

在这第三个场景中,插入到数据库的值与第一个场景中插入的值相同。
为什么会这样呢?无论在哪种情况下,hash()函数的调用方式都是相同的。它在代码中的位置是唯一的不同之处。当hash()函数直接在SQL查询中调用而非通过<cfqueryparam>值或<cfset>时,似乎会发生一些奇怪的事情。

ColdFusion 的特定版本? - James A Mohler
1
这两个字符串中是否有空格或任何特殊字符? - James A Mohler
@JamesAMohler 它正在运行 ColdFusion 8。字符串中肯定有空格,可能还包含特殊字符。 - Ryan Covert
当输入不是来自文本框而是常量字符串时,哈希值是否会有所不同? - Bernhard Döbler
@BernhardDöbler 文本的来源似乎对结果没有任何影响。在测试中,我将原始文本值放入<cfsavecontent>中,并获得了相同的结果。 - Ryan Covert
1个回答

1
我猜测:

这只是我的半吊子猜测。

<cfquery></cfquery>并不完全等同于<cfsavecontent></cfsavecontent>。我认为&并不是普通的字符串连接。因此,这里有一个测试来验证我的假设。请尝试以下内容:

<cfset hashed_value = hash("" &first_string & second_string, "MD5")>
<cfquery name="my_query" datasource="#my_datasource_name#">
    INSERT INTO my_table
    (
        md5_hashed_value
    )
    VALUES
    (
        '#hashed_value#'
    )
</cfquery>

这是否与之前的操作相同?我怀疑是相同的。

<cfquery name="my_query" datasource="#my_datasource_name#">
    INSERT INTO my_table
    (
        md5_hashed_value
    )
    VALUES
    (
        '#hash("" & first_string & second_string, "MD5")#'
    )
</cfquery>

这是否和以前做的一样?我怀疑不是。

解决方法

<cfquery name="my_query" datasource="#my_datasource_name#">
    DECLARE @md5_hashed_value = '#hash(first_string & second_string, "MD5")#'

    INSERT INTO my_table
    (
        md5_hashed_value
    )
    VALUES
    (
        @md5_hashed_value
    )
</cfquery>

虽然这种方法没有<cfqueryparam>的所有好处,但至少它对查询进行了参数化处理。


感谢您对DECLARE的建议。不幸的是,在SQL语句中,无论inline hash()在字符串中出现在哪里,它在ColdFusion中最终都会得到不同的值。 - Ryan Covert
1
我现在已经针对最新的Lucee版本进行了测试,没有出现相同的问题。我还尝试将UTF-16指定为所有调用hash()的字符编码,但无济于事。使用nvarchar作为列类型的临时表进行测试应该会产生相同的值,无论数据库排序规则如何,但也许排序规则是潜在的问题。此时,我准备更新此代码的所有位置,以便使用最初预期的<cfqueryparam>并处理任何后果。 - Ryan Covert
你可以使用<cfqueryparam>来提高一些性能。不过,你也可以考虑使用QueryExecute - James A Mohler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接