【问题标题】:Coldfusion: authenticating hashed passwordColdfusion:验证散列密码
【发布时间】:2013-05-28 15:40:44
【问题描述】:

我有一个登录验证系统,数据库中的密码存储为 SHA-384。当我包含 Hash 函数时,以下登录脚本什么都不做。我哪里错了?

我正在使用 MSSQL Server 2008 R2,Coldfusion 10。

loginform.cfm

<cfif IsDefined("FORM.email")>
  <cfset redirectLoginSuccess="admin.cfm">
  <cfset redirectLoginFailed="login.cfm">
  <cfquery  name="UserAuth" datasource="sql1007539">
  SELECT email,userPass FROM customers WHERE email=<cfqueryparam value="#FORM.email#" cfsqltype="cf_sql_clob" maxlength="255"> 
  AND userPass=<cfqueryparam value="#Hash(form.userPassword, "SHA-384")#" cfsqltype="cf_sql_clob" maxlength="255">
  </cfquery>
  <cfif UserAuth.RecordCount NEQ 0>
    <cftry>
      <cflock scope="Session" timeout="30" type="Exclusive">
        <cfset Session.Username=FORM.email>
        <cfset Session.UserAuth="">
      </cflock>
      <cfif IsDefined("URL.accessdenied") AND true>
        <cfset redirectLoginSuccess=URL.accessdenied>
      </cfif>
      <cflocation url="#redirectLoginSuccess#" addtoken="no">
      <cfcatch type="Lock">
      </cfcatch>
    </cftry>
  </cfif>
  <cflocation url="#redirectLoginFailed#" addtoken="no">
  <cfelse>
  <cfset LoginAction=CGI.SCRIPT_NAME>
  <cfif CGI.QUERY_STRING NEQ "">
    <cfset LoginAction=LoginAction & "?" & XMLFormat(CGI.QUERY_STRING)>
  </cfif>
</cfif>

编辑:如果不使用 HASH 函数,该脚本可以工作。 编辑:我还可以确认密码存储在 SHA-384 中。我使用以下 HASH 标识符进行了检查:duncanwinfrey.com/tools/hashid/hash.php

29/05/13 编辑

**代码返回错误,当我删除 cfparam 标记 **

<cfquery  name="UserAuth" datasource="sql1007539">
  SELECT email,userPass FROM customers WHERE email="#FORM.email#" 
  AND userPass="#hash(form.userPassword, "sha-384")#"
  </cfquery>

返回错误

【问题讨论】:

  • 它什么都不做?你看到了什么?它加载吗?可以提交吗?您是否已验证参数正在进入服务器页面?当你说它在没有哈希的情况下工作时,这意味着你成功登录了吗?如果是这个原因,很可能您的密码没有在数据库中散列。检查您的customers 表:如果您可以以纯文本形式读取密码,那么密码永远不会被散列。在查找它们之前调用它们的哈希函数是行不通的。如果您希望它们被散列,则必须计算散列并将其存储回表中。
  • 您是否比较了 DB 执行 SHA-384 哈希和 CF 执行相同操作的结果? IE:使用已知密码,并将其添加到系统中。从数据库表中提取其哈希。使用 CF 同样散列相同的纯文本密码。比较两者的结果。事物的编码/存储方式可能会有所不同,您需要在两个系统之间进行结合。
  • 您的 SQL customers.userPass 的数据类型是什么?它也是一个CLOB吗?它需要是CLOB吗?尝试不使用 cfqueryparam 进行测试,看看是否是您的 cfsqltype 的问题。将您的查询更改为 ...AND userPass= '#Hash(form.userPassword, "SHA-384")#'。看看你是否可以让它以这种方式识别你的散列密码。在将其投入生产之前不要忘记将其改回。
  • 是的,它们存储正确您需要更具体地说明您尝试了哪些故障排除步骤;-) Adam 就如何解决问题提供了一些非常好的建议。您应该能够使用它们来组合一个可靠的repro case,您可以将其包含在您的问题中。在此过程中,您可能会自己找出问题所在。但即使你不这样做,发布一个其他人可以独立测试的示例也会导致更快的答案,因为它消除了猜测。
  • 该错误是由双引号引起的。 sql 值需要单引号。 userPass='#Hash(form.userPassword, "SHA-384")#' 同样,确保在投入生产之前将 cfqueryparam 放回原处。这只会帮助您排除故障。我仍然不确定为什么密码字段需要是 CLOB。如果可以的话,Peter 有一个很好的建议,可以切换到 char()。数据库中密码字段的实际数据类型是什么?

标签: hash coldfusion


【解决方案1】:

我会解决编码问题。我相信 CLOB/BLOB 通常是 Oracle 或 DB2 数据类型,而不是 MS SQL Server 的原生数据类型。我认为您不能将 CLOB/BLOB 指定为 SQL Server 中的数据类型。当您将 cf_sql_clob 传递到 cfqueryparam 时,它使用 JDBC 驱动程序在与 SQL Server 对话时尝试转换为文本或 varchar(max)。翻译中可能会丢失一些东西。由于您要连接到 SQL Server,请尝试将正确的数据类型传递给 cfqueryparam。查看 email 和 userPass 的数据库列的属性。您应该能够将 cfsqltype 设置为 cf_sql_char 或 cf_sql_varchar。我有点惊讶查询没有抛出错误,但是错误可能被数据类型转换掩盖了,而且它根本没有返回任何结果。

http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7f6f.html

http://msdn.microsoft.com/en-us/library/ms378813(v=sql.105).aspx

编辑: 尝试将您的查询更改为:

SELECT email,userPass FROM customers 
WHERE email = <cfqueryparam value="#FORM.email#" cfsqltype="cf_sql_varchar" maxlength="255"> 
AND userPass = <cfqueryparam value="#Hash(form.userPassword, "SHA-384")#" cfsqltype="cf_sql_varchar" maxlength="255">

【讨论】:

  • 对编辑感到抱歉。它一直在逃避我的 cfqueryparams 并且不允许我正确格式化代码。 :-S
  • 谢谢肖恩,我已经付诸行动了。
  • Shawn 我已经在答案中发布了解决方案。 :-)
【解决方案2】:

在专家交流论坛 (agx) 的帮助下,我设法让它工作。事实证明这是我的人为错误。我在注册过程的插入查询中有一个额外的空间,并将编码设置为 UTF-8:

'(空格)#hash(form.password, "sha-384" ,'UTF-8')#'

我将密码类型更改为char(96),并按照建议修改了cfqueryparam。谢谢大家的帮助和指导。以下是故障排除代码,我曾经帮助我解决这个问题:

输入现有条目的电子邮件和密码,以从数据库中获取记录:

<cfset form.email = "some known email">
<cfset form.userPassword = "real password before hashing">

<!--- ONLY match on email ---->
<cfquery name="qGetData" ....>
     SELECT  * 
     FROM    yourTable
     WHERE   email =<cfqueryparam value='#FORM.email#' 
                            cfsqltype="cf_sql_varchar">
</cfquery>

<!--- Checking to see if the password is hashed or is in clear text --->
<cfdump var="#qGetData#">

对明文密码进行哈希处理,并将其与 db 值进行比较。

<cfset newhash = hash(form.userPassword,'SHA-384')>
<cfif compare(newHash, qGetData.userPass) eq 0>
    SAME
<cfelse>
    DIFFERENT
</cfif>

乍一看,这些值看起来是一样的。为了确保 db 中存储的密码和登录表单中的密码相同,使用了以下代码:

<cfoutput>
   db |#qGetData.userPass#|<br>
   form |#hash(form.userPassword,'SHA-384')#|<br>
</cfoutput>

然后我使用了handy website to compare the outputs。结果又是一样的。经过这么多的努力,原来#hash(...)#前面多了一个空间。

【讨论】:

  • RE:结果是一样的干得好。但是,如果有一个额外的前导空格,则进行一个更正,那么值就不一样了。该在线工具默认忽略空白,因此除非您更改默认选项,否则您不会看到差异。
  • 我什至数不清有多少次我因数据库中意外的前导/尾随空格,甚至更糟糕的从 Word 复制/粘贴转移过来的特殊字符而撞到墙上。 Grrrr.... 很高兴你把它修好了 Caludia。
【解决方案3】:

使用双引号时,值被解析为对象(表、列等)。 始终坚持使用安全且快速的 cfqueryparam。

尝试在哈希函数中添加第三个参数来强制使用不同的编码;例如:

<cfquery  name="UserAuth" datasource="sql1007539">
  SELECT email,userPass FROM customers WHERE email=<cfqueryparam value="#FORM.email#" cfsqltype="cf_sql_clob" maxlength="255"> 
  AND userPass=<cfqueryparam value="#Hash(form.userPassword, "SHA-384", "UTF-8")#" cfsqltype="cf_sql_clob" maxlength="255">
  </cfquery>

注意 UTF-8 参数。常用编码有:ISO-8859-1、ISO-8859-11 (Latin9)。

Gl!

【讨论】:

  • 我相信 CF 散列函数中的编码参数有问题,并不总是像宣传的那样工作。我知道它曾经是。不知道是不是还是这样。
【解决方案4】:

不确定这是 typeo 还是您的代码直接复制粘贴:

您实际上是在使用 value 属性的哈希函数内的双引号轰炸您的 cfquery 标记。

  • 你有这个:value="#Hash(form.userPassword, "SHA-384")#"
  • 将其替换为:value="#Hash(form.userPassword, 'SHA-384')#"

请注意 SHA-384 值周围的单引号。这应该可以解决您的问题。

【讨论】:

  • 不,它对"#do("this")#" 完全有效——它工作正常并且不会导致任何错误。如果你疯了,你甚至可以做"#"#"this"#"#" 之类的东西,它仍然可以工作,(即使人眼很难跟随)。
  • 感谢您的建议 Brett,尝试您的建议后仍然没有成功。
  • (p.s. 刚刚注意到问题中的语法着色问题可能触发了这个响应 - 所以澄清一下,这是 SO 语法高亮的一个缺陷,它不知道 CFML,因此不知道它应该将哈希的内容视为表达式。)
猜你喜欢
  • 1970-01-01
  • 2020-08-16
  • 2016-05-22
  • 2020-02-29
  • 2019-05-24
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多