Tomcat无法重定向到400自定义错误页

20

我们在生产环境中使用的是Tomcat 9 Web服务器。我们面临的问题是,如果Tomcat收到以下任何格式错误的URL,我们希望为我们的应用程序显示自定义错误页面:

http://URL/|

或者

http://URL/[

我已经在Tomcat应用程序服务器的web.xml文件中添加了错误页面标签,如下所示:

<error-page>
   <error-code>400</error-code>
   <location>/error.html</location>
 </error-page>
 <error-page>
   <error-code>404</error-code>
   <location>/error.html</location>
 </error-page>

我们的应用程序根文件夹中有一个名为 error.html 的文件,位于 Tomcat 的 webapps 目录中。

每当用户尝试请求任何不存在的网页时,他会正确地收到对应于 404 错误代码的错误页面,如上所述。

真正的问题是,当用户在浏览器中输入类似于 http://URL/| 的格式不正确的 URL 时,Tomcat 无法重定向到 error.html。

Tomcat 显示默认的 400 错误请求错误页面,而不是自定义错误页面。


1
我们遇到了完全相同的问题。你最终解决了吗?谢谢。 - stepanian
仍然无法解决@stepanian。 - Pawan Patil
看起来这更像是一个错误而不是我们做错了什么。我们应该通知Tomcat开发团队。 - stepanian
这个问题只存在于Tomcat 9中。在Tomcat7和Tomcat8中都可以正常工作。@stepanian - Pawan Patil
是的。在我的Tomcat 8中也可以工作。看起来这是Tomcat 9引入的一个bug。 - stepanian
4个回答

24

这不是一个错误,而是一个配置问题。

Tomcat 9 改进了错误处理机制,以便更多的错误(特别是在请求处理开始之前发生的错误)被传递到标准错误处理机制,而不仅仅返回错误代码。

对于格式错误的 URI,Tomcat 无法解析该 URI,因此无法将其映射到 Web 应用程序。因此,Tomcat 无法触发应用程序级别的错误处理,因为它无法识别应用程序。在这种情况下,错误由 ErrorReportValve 处理,可以在 server.xml 中进行配置。

ErrorReportValve 的最近(ish) 新增功能包括类似于每个 Web 应用程序错误页面配置的方式,能够定义静态 Web 页面(即没有 Servlet 或 JSP,只有 HTML),针对每个状态码和/或异常类型。

示例错误报告阀门:

<Valve className="org.apache.catalina.valves.ErrorReportValve"
        errorCode.400="webapps/ROOT/error400.html"
        errorCode.0="webapps/ROOT/errorOthers.html"
        showReport="false"
        showServerInfo="false" />

2
我似乎在Tomcat文档或其他任何地方找不到如何配置ErrorReportValve以返回预定义的静态HTML页面的示例。你能给我指出一些例子吗? - CFL_Jeff
@CFL_Jeff。请查看https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Error_Report_Valve。 - gordon613
是的,现在已经为Tomcat 9.0.53实现了它,并且它可以正常工作。谢谢。我建议注意errorCode.0的特殊值。这样,如果服务器有多个上下文,您就可以集中保护整个服务器。 - Paul Uszak
@Paul Uszak,虽然我在你的答案中提到的位置上有自定义HTML文件来处理400错误,但这个答案对我不起作用。只有默认的Tomcat 400错误页面不断弹出。我想要我的custom400error.html在屏幕上呈现。请帮忙解决。 - MdBasha
@MdBasha 我有以下代码:<!-- 这个阀门用于防止400错误返回Tomcat信息 --> <Valve className="org.apache.catalina.valves.ErrorReportValve" errorCode.0="webapps/ROOT/404.html" showReport="false" showServerInfo="false" /> - Paul Uszak
显示剩余8条评论

9
以下是遵循 https://dev59.com/glQJ5IYBdhLWcg3w66bM#55702749 的示例配置,以节省他人的时间。 在 Host 标签内的 server.xml 文件中:
  <Valve className="org.apache.catalina.valves.ErrorReportValve"
        errorCode.400="webapps/ROOT/error400.html"
        errorCode.0="webapps/ROOT/errorOthers.html"
        showReport="false"
        showServerInfo="false" />

将静态的html错误页面error400.html ... errorOthers.html放置在CATALINA_BASE的webapps/ROOT目录中。


CATALINA_BASE在哪里? - CodificadorD
@CodificadorD - 如果您没有定义它,它将默认为CATALINA_HOME。 - kosolapyj
@kosolapyj,这对我不起作用,尽管我在你的答案中提到的位置上有HTML文件。只有400的默认错误页面不断弹出。我想要我的custom400error.html在屏幕上呈现。请帮忙解决。 - MdBasha

1

之前的解决方案在我的情况下没有起作用。

根据Tomcat文档,阀门组件可以放置在容器引擎、主机或上下文中。

我已经尝试了所有方法,但对于这个特定的400错误却毫无进展(其他错误都按预期处理)。

最后我发现这个谜题中缺失的元素:

为了提高效率,奇怪的是,错误报告阀门必须放置在被定义为catalina引擎的defaultHost的主机容器中,即使它不是目标主机。

server.xml示例: 同时处理“some-cats.com”和“some-dogs.com”的错误请求400。

<Engine name="Catalina" defaultHost="www.some-dogs.com">
    <!--     NO EFFECT ON ERROR PAGE 400
    <Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" /> 
    -->
    <Host name="www.some-cats.com">      
        <!--     NO EFFECT ON ERROR PAGE 400
        <Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" /> 
        -->
        ...
    </Host>
    <Host name="www.some-dogs.com">
        <!--  HERE IS THE RIGHT PLACE FOR ERROR PAGE 400-->
        <Valve className="org.apache.catalina.valves.ErrorReportValve" errorCode.0="path/error.html" showReport="false" showServerInfo="false" />
        ...
    </Host>
</Engine>

已在Tomcat 8.5.84和9.0.70上进行了测试。

当然,如果您只有一个主机,则不会遇到此问题。


0

尽管我在你的答案中提到的位置上有HTML文件和JAR文件,但这对我没有用。只有400的默认错误页面不断弹出。我想要我的custom400error.html在屏幕上呈现。请帮忙解决。 - MdBasha

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