关于ColdFusion的CGI范围/结构的未记录的不一致行为

时间:2018-02-15 03:24:59

标签: coldfusion coldfusion-9 coldfusion-10 coldfusion-11 coldfusion-2016

我最初发布这个作为这个问题的答案,早先关于Empty CGI.REDIRECT_URL on ColdFusion 2016。在考虑之后,我认为更好,因为技术上没有回答OP的问题。相反,我决定把它变成一个单独的问题,尽管它更像是一个评论而不是一个问题。虽然这在技术上可能无法满足Minimal, Complete, and Verifiable example的全部要求而且人们可能会给我带来帮助,但我认为无论如何它都值得,希望它能够更容易找到以便将来使用有可能遇到这种情况的CFers。因此,就CGI结构/范围的这种特殊行为而言,防止它们撞到墙上。

话虽如此,CGI结构/范围与其他结构/范围有一些未记录的不一致行为。请注意,我个人对此发现不予赞同,因为我在阅读Ben Nadel's blog post on this之前发生过这段时间。所以我在这里发布的所有信息都已在那里详细说明了,但我想在这里写一篇很好的摘要。

  

未记录的行为1 - 与其他结构不同,如果CGI结构键不存在,那么在引用它时不会抛出错误。

OP's original question中,他想知道为什么cgi.REDIRECT_URL存在但是空洞。正如他最终发现的那样,它从未真正存在过。作为一个单独的示例,您可以执行此行代码而不会抛出错误。不是你期望的,呵呵?

<cfoutout>#cgi.THIS_IS_A_FAKE_KEY#</cfoutout>

那么CFer要做什么?测试密钥的存在。

<cfif structKeyExists( CGI, 'THIS_IS_A_FAKE_KEY' )>
    THIS_IS_A_FAKE_KEY exists
<cfelse>
    THIS_IS_A_FAKE_KEY doesn't exist
</cfif>
  

未记录的行为2 - 与其他结构不同,如果您转储CGI结构,它不会显示所有键/值对,它只会显示一组已定义的键。 < / p>

OP's case中,他有一个自定义的Apache CGI变量cgi.REDIRECT_URL,在升级到CF2016之前在他的代码中使用,并且可以直接引用它。但是,我假设他是否抛弃了cgi结构,它不会出现在转储中。在Ben Nadel's case中,他还有一个名为cgi的自定义cgi.document_root变量,该变量从负载均衡器传来,并且可以直接引用它,但他也不能转储cgi内容时看到密钥。

那么CFer要做什么?理解这一点并将其存储在您的脑海中,这样当您转储cgi内容并且键/值对不在那里时,您就不会被咬住。除此之外,其他并不多。

2 个答案:

答案 0 :(得分:7)

我进入了ColdFusion的cfusion.jar文件。我发现那里有点令人困惑。

CGI范围不是人们希望的structure形式。

这是如何处理对CGI变量的调用。例如<cfoutout>#cgi.THIS_IS_A_FAKE_KEY#</cfoutout>

  1. 正常有效的CGI范围变量是此列表中的变量,默认情况下这些变量将初始化为""

    private static final String[] names ="AUTH_PASSWORD","AUTH_TYPE","AUTH_USER","CERT_COOKIE","CERT_FLAGS","CERT_ISSUER","CERT_KEYSIZE","CERT_SECRETKEYSIZE","CERT_SERIALNUMBER","CERT_SERVER_ISSUER","CERT_SERVER_SUBJECT","CERT_SUBJECT","CF_TEMPLATE_PATH","CONTENT_LENGTH","CONTENT_TYPE","CONTEXT_PATH","GATEWAY_INTERFACE","HTTP_ACCEPT","HTTP_ACCEPT_ENCODING","HTTP_ACCEPT_LANGUAGE","HTTP_CONNECTION","HTTP_COOKIE","HTTP_HOST","HTTP_USER_AGENT","HTTP_REFERER","HTTP_URL","HTTPS","HTTPS_KEYSIZE","HTTPS_SECRETKEYSIZE","HTTPS_SERVER_ISSUER","HTTPS_SERVER_SUBJECT","LOCAL_ADDR","PATH_INFO","PATH_TRANSLATED","QUERY_STRING","REMOTE_ADDR","REMOTE_HOST","REMOTE_USER","REQUEST_METHOD","SCRIPT_NAME","SERVER_NAME","SERVER_PORT","SERVER_PORT_SECURE","SERVER_PROTOCOL","SERVER_SOFTWARE","WEB_SERVER_API" };`
    

    所有这些值也来自各种Java库javax.servletHttpServletRequest等。

  2. 如果请求的变量在经过一些检查后不是任何变量,ColdFusion会转到请求标头。您可以使用getHttpRequestData().headers查看这些内容。然后在-密钥请求中查找带有连字符(_)而不是下划线(cgi)的密钥。 (如果密钥以http_开头,则请求标头中的密钥将不会显示,请求标头中的http_x_forward将为x-forward

    value = request.getHeader(name.replace('_', '-'));
    
  3. 据我所知,就ColdFusion而言,第一点提到的密钥是公认的CGI范围的一部分。但是当从Apache负载均衡器服务器向ColdFusion传递其他信息时,这些信息最终会出现在请求标头中。由于java getHeader只返回一个空字符串(或数据类型为undefined的内容)而不是未定义的错误, ColdFusion无法识别是否定义了任何键

    因此,如果密钥THIS_IS_A_FAKE_KEY从诸如Apache服务器之类的中介发送到ColdFusion。您将在getHttpRequestData().headers['THIS-IS-A-FAKE-KEY']但不在CGI范围转储中找到它。

    据我所知,我个人认为最好直接在getHttpRequestData().headers中查看除范围本身以外的自定义CGI变量。

答案 1 :(得分:7)

编辑感谢Ageax指出我的一个测试用例在我之前修订的这篇文章中无效。

RRK的大量侦探工作!所以我决定通过创建两个循环来执行实验以验证您的发现。第一个循环将显示来自getHttpRequestData().headers的键/值对,第二个循环使用cgi范围内的相应键/值对执行相同操作,将-替换为{{1} }}。瞧!正如RRK报道的那样,我们可以看到如何通过任一方法获得值。我提出了更新的要点,并为感兴趣的人发布了here

_