【问题标题】:ColdFusion 10 + IIS: Non-existant URLs that are CFM files. Retrieving original URL after executing 404 pageColdFusion 10 + IIS:作为 CFM 文件的不存在的 URL。执行 404 页面后检索原始 URL
【发布时间】:2013-09-12 17:56:01
【问题描述】:

我们的服务器设置如下:

  • Windows 2012 R2
  • Coldfusion 10,企业
  • IIS,配置自定义 404 页面(在服务器上执行)

自定义 404 页面(一个 CFM 文件)处理丢失的 URL,并根据数据库中的自定义 URL 检查它们。如果找到匹配项,它将显示相关数据。当自定义 URL 映射到不存在的 CFM 文件时会出现问题;例如。

/home/map.cfm(不是真正的文件或目录)

现在,当用户请求此 URL 时,服务器会看到它是一个 CFM 文件并正确地将其传递给 ColdFusion(通过 ISAPI 重定向)。 Tomcat 看到这个文件实际上并不存在,并返回一个 404。IIS 看到这个 404 消息并执行自定义错误页面(/errors/404.cfm)。

生成的 CGI 变量实际上不允许我们检索原始 URL(将其映射到数据库中的虚拟 URL),通常作为 CGI.QUERY_STRING 变量的一部分提供。相反,QUERY_STRING 变量包含“jakarta”目录中“isapi_rewrite.dll”文件的路径。

在 Tomcat 为所述页面返回 404 错误后,有什么方法可以保留最初请求的(CFM 文件的)URL?

解决方案,由 Thomas Gorgolione 启发,由我自己编写

正如怀疑的那样,问题总是归结为请求被转发到 ISAPI_REDIRECT 模块,即使相关文件不存在。

正如 Thomas 所建议的,一个优雅的解决方案是在将文件/目录传递给 ISAPI_REDIRECT 模块之前,利用重写来检查文件/目录是否确实存在。

虽然 Thomas 建议的软件可以解决问题,但我无法将其安装在 64 位 Windows 2012 R2 机器上。但是,我设法回退到使用 IIS8(可能还有早期版本)中包含的 URL 重写模块。

请参阅下面提供解决方案的我的 web.config 条目。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors>
            <remove statusCode="404" subStatusCode="-1" />
        </httpErrors>
        <rewrite>
            <rules>
                <rule name="404 HTTP">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{REQUEST_URI}" pattern="CFFileServlet/(.*)" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                        <add input="{SERVER_PORT_SECURE}" pattern="0" />
                    </conditions>
                    <action type="Rewrite" url="/404.cfm?404;http://{HTTP_HOST}:{SERVER_PORT}{REQUEST_URI}" />
                </rule>
                <rule name="404 HTTPS">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{REQUEST_URI}" pattern="CFFileServlet/(.*)" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                        <add input="{SERVER_PORT_SECURE}" pattern="1" />
                    </conditions>
                    <action type="Rewrite" url="/404.cfm?404;https://{HTTP_HOST}:{SERVER_PORT}{REQUEST_URI}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

上述配置文件同时考虑了 HTTP 和 HTTPS 请求。它还将考虑 CFFileServlet 目录,ColdFusion 使用该目录来托管临时图像和资产。如果 URL 以该目录开头,它将作为正常请求传递。

感谢大家的意见。

【问题讨论】:

    标签: tomcat iis coldfusion


    【解决方案1】:

    注意:上述问题也包括解决方案。

    我认为这是 Coldfusion 连接器的错误。我会向 Adob​​e (https://bugbase.adobe.com/) 发布错误报告。我确实有一个解决方法。我有同样的问题,但我使用 IIRF(Ionic IIS Redirector - http://iirf.codeplex.com/),我找到了一种方法来使用它来避免现在的错误:

    1. 在 IIS/Coldfusion 中删除任何以前的 404 文件配置
    2. 按照 IIRF 的安装说明正常安装。
    3. 在 IirfGlobal.ini 文件(通常位于 C:\Windows\System32\inetsrv\IIRF)中,添加以下行:

      RewriteFilterPriority HIGH
      

      这将允许 IIRF 在到达 ColdFusion/Tomcat 之前处理 404 请求。

    4. 在特定于站点的 Iirf.ini 中(通常您在 Web 文件的根文件夹中创建一个 - 有关详细信息,请参阅 IIRF 文档),添加以下规则:

      RewriteCond %{SCRIPT_TRANSLATED} !-f
      RewriteCond %{SCRIPT_TRANSLATED} !-d
      RewriteRule ^(.+)$ page_to_redirect_to.cfm?404;$1 [L]
      

      这会将所有不存在的文件/目录重定向到page_to_redirect_to.cfm,并像往常一样添加404查询字符串。

    5. 编辑:添加了以下步骤: 进入 IIS 管理器并选择配置为使用 IIRF 的服务器或网站,然后进入 ISAPI 过滤器部分。点击“查看有序列表”,然后将 IIRF 过滤器移至顶部。

    编辑 2:刚刚向 Adob​​e 发布了一个错误。见https://bugbase.adobe.com/index.cfm?event=bug&id=3630245

    希望对您有所帮助。

    【讨论】:

    • 很好,谢谢 Thomas - 我现在就在我们的开发服务器上尝试一下。
    • 这看起来像是一个可行的解决方案,但不幸的是,IIRF 未能在我们的服务器上安装,在 MSIEXEC 日志文件中提供了一个完全无用的错误代码。我们也许可以使用另一个重写模块,例如 Helicon 来实现相同的目标。
    • 我接受你的回答,因为你让我走上了解决这个问题的正确道路。最后,我实际上使用了 IIS 8 中包含的 URL Rewrite 模块来达到同样的效果。我在我的问题中包含了 web.config 条目,作为其他人的参考。非常感谢。
    • 太棒了,谢谢!我将编辑问题(注意到我需要输入一个额外的步骤),并在顶部注明您的解决方案。
    • 是的,任何 URL 重写模块都应该这样做,只要它在 ColdFusion 之前运行
    【解决方案2】:

    让我先声明我仍在运行 ColdFusion 9,因此我没有第一手经验来使用 Tomcat 在 ColdFusion 10 中处理 404。显然我需要升级到版本 10,所以我试图让自己熟悉它的细微差别(比如处理 404)。所以我做了一些搜索。

    正如您在问题中所述,对于 ColdFusion 9 和 IIS,最初请求的文件通常包含在前面带有“404;”的 CGI.QUERY_STRING 变量中。对于 ColdFusion 10 和 Tomcat,它看起来好像其他一些 CGI 变量包含最初请求的文件,这取决于您的设置是哪个变量。

    我发现了 Raymond Camden 的这篇博文 - Reminder--there-is-more-to-the-CGI-scope-than-what-the-dump-shows。虽然这本身包含了很好的信息,但我还在 Jules Gravinese 的 cmets 中找到了以下内容:

    使用 IIS7 时,变量为 CGI.HTTP_X_ORIGINAL_URL

    使用ISAPI_rewrite时,变量为CGI.HTTP_X_REWRITE_URL

    使用 APACHE 时,变量为 CGI.REDIRECT_URL

    我还发现了一些引用 CGI.REDIRECT_QUERY_STRING 变量的其他文章,我相信在使用 APACHE 时也包含该变量。


    从 Adob​​e 找到另一篇关于 CGI 变量以及它们如何与 ColdFusion 一起使用的文章(以及如何/为什么它不是完整列表):CGI environment (CGI Scope) variables


    注意:我还发现了这个错误ColdFusion 10.0 - Bug 3488063: IIS 404 custom error handler URLs that are .cfm files do not consistently return entire document,它已被关闭,但最近的几个 cmets 表明它仍然是一个问题。所以请注意这一点。

    【讨论】:

    • 感谢您的输入 - 我不知道“隐藏”CGI 字段。不幸的是,在请求期间这些字段都不存在。另外,感谢您对不完整文档的附注。我们已经与这个错误进行了斗争,并取得了成功(强制使用“连接:关闭”标题,并禁用动态压缩)。
    • 令人惊讶的是,这个功能是多么没有文档记录。我发现的一切都指向我提到的 CGI 变量。不知道为什么你没有看到他们?不幸的是,我没有可使用的 CF10 安装。希望其他人会加入。
    【解决方案3】:

    使用Application.cfc OnMissingTemplate method 处理丢失的模板页面。

    在 Application.cfc 中添加这个

    <cffunction name="onMissingTemplate">
        <cfargument name="targetPage" type="string" required=true/>
    
        <!--- No standard error handling here so we need to try/catch --->
        <cftry>
            <!--- Can't do a redirect so we'll do an "include" --->
            <cfset missingPage=Arguments.targetPage>
            <cfinclude template="/errors/404.cfm">
    
            <cfcatch>
              <!--- Let the standard missing file (404) process occur --->
                <cfreturn false />
            </cfcatch>
        </cftry>
    </cffunction>
    

    在 /errors/404.cfm 中在顶部附近添加此内容

    <cfparam name="missingPage" type="string" default="">
    <cfif missingPage eq "">
      <!--- Include CGI variable and process as fitting for your purposes --->
      <cfset missingPage=CGI.QUERY_STRING>
    </cfif>
    

    【讨论】:

    • 谢谢,但目前这不是一个选项,老实说,我们在 IIS 中使用 Application.cfc 错误设置时遇到过很多糟糕的经历。
    • 我明白了。那些与做 cflocation 有关吗?它非常具体地说明了您可以调用和不能调用的内容。
    • @Seidr 你能解释一下你的解决方案吗?我也遇到了这个问题(回复:stackoverflow.com/q/17956552/159710
    • @ShawnE 未执行 CFLocation,此请求直接指向不存在的 CFM 文件。
    • @RHPT 目前还没有找到解决方案。奇怪的是,如果我们将“虚拟”路径更改为子文件夹(在本例中为 /home/map)并在路径中包含 index.cfm(默认文档)(导致 /home/map/index.cfm )。这会在访问 /home/map 时使用正确的 QUERY_STRING 命中 404 处理程序,而直接访问 /home/map.cfm 则不会。很奇怪。
    猜你喜欢
    • 2016-06-28
    • 1970-01-01
    • 2013-07-31
    • 2012-12-09
    • 1970-01-01
    • 2011-07-01
    • 2014-10-04
    • 1970-01-01
    • 2017-11-24
    相关资源
    最近更新 更多