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

use*_*373 5 coldfusion coldfusion-9 coldfusion-10 coldfusion-11 coldfusion-2016

我最初发布这个作为早期关于ColdFusion 2016上的空CGI.REDIRECT_URL的问题的答案.在考虑之后,我认为它更好,因为技术上没有回答OP的问题.相反,我决定把它变成一个单独的问题,尽管它更像是一个评论而不是一个问题.虽然这在技术上可能无法满足最小,完整和可验证的例子的全部要求,而且人们可能会给我带来帮助,但我认为它还是值得的,希望能够更容易找到未来可能遇到此问题的CFers .因此,关于CGI结构/范围的这种特殊行为,防止它们撞到墙上.

话虽如此,CGI结构/范围与其他结构/范围有一些未记录的不一致行为.请注意,我个人对这一发现不予理睬,因为我在阅读Ben Nadel的博客文章时发生过这段时间.所以我在这里发布的所有信息都已在那里详细说明,但我想在这里写一篇很好的总结.

未记录的行为1 - 与其他结构不同,如果CGI结构键不存在,则在引用它时不会引发错误.

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

<cfoutout>#cgi.THIS_IS_A_FAKE_KEY#</cfoutout>
Run Code Online (Sandbox Code Playgroud)

那么什么是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>
Run Code Online (Sandbox Code Playgroud)

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

OP的情况下,他有一个自定义的Apache CGI变量cgi.REDIRECT_URL,在升级到CF2016之前在他的代码中使用,并且能够直接引用它.但是,我假设他是否抛弃了cgi结构,它不会出现在转储中.在Ben Nadel的案例中,他还有一个自定义cgi变量,称为cgi.document_root从负载均衡器传递并且能够直接引用它,但是在转储cgi内容时他也无法看到密钥.

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

RRK*_*RRK 7

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

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" };`
    
    Run Code Online (Sandbox Code Playgroud)

    此外所有这些值也来自不同的Java库javax.servlet,HttpServletRequest等等.

  2. 如果在经过一些检查后请求的变量不是任何变量,ColdFusion会转到请求标头.你可以看到这些使用getHttpRequestData().headers.然后在键请求中查找带有连字符(-)而不是下划线(_)的cgi键.(如果所述密钥与开始http_,则在请求标题密钥将与出像这样http_x_forward在请求报头将是x-forward)

    value = request.getHeader(name.replace('_', '-'));
    
    Run Code Online (Sandbox Code Playgroud)

据我所知,就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变量.


use*_*373 7

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

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

<cfset httpHeaders = getHttpRequestData().headers>

<h3>getHttpRequestData().headers</h3>

<cfloop collection="#httpHeaders#" item="key" >
    <cfoutput><strong>#Key#</strong> : #httpHeaders[key]#<br></cfoutput>
</cfloop>

<h3>cgi keys dash to underscore</h3>

<cfloop collection="#httpHeaders#" item="key" >
    <cfset keyUnderscore = replace(key, "-", "_", "all")>
    <cfoutput><strong>#keyUnderscore#</strong> : #cgi[keyUnderscore]#<br></cfoutput>
</cfloop>
Run Code Online (Sandbox Code Playgroud)