禁用Tomcat中的所有默认HTTP错误响应内容

Rob*_*ska 67 java tomcat servlets http httpresponse

默认情况下,Tomcat的发送一些HTML内容返回给客户端,如果遇到类似的HTTP 404.我知道,通过web.xml一个<error-page> 可配置自定义此内容.

但是,我只是希望Tomcat 不要在响应内容方面发送任何内容(当然我仍然喜欢状态代码).有没有办法轻松配置这个?

我试图避免A)从我的Servlet中明确地在响应流上发送空内容,以及B)为我的一大堆HTTP错误状态配置自定义错误页面web.xml.

在某些背景下,我正在开发一个HTTP API并控制自己的响应内容.因此,对于HTTP 500,我在包含错误信息的响应中填充一些XML内容.对于像HTTP 404这样的情况,HTTP响应状态对于客户端来说已经足够了,并且tomcat发送的内容是不必要的.如果有不同的方法,我愿意听到它.

编辑: 继续调查后,我仍然找不到解决方案的方法.如果有人可以明确地说这是不可能的,或者提供资源证明它不起作用,我会接受这个作为答案并尝试解决它.

小智 45

如果您不希望tomcat显示错误页面,则不要使用sendError(...).而是使用setStatus(...).

例如,如果你想给出405响应,那么你就做了

response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);      
response.getWriter().println("The method " + request.getMethod() + 
   " is not supported by this service.");
Run Code Online (Sandbox Code Playgroud)

还记得不要从servlet中抛出任何异常.而是捕获异常,并再次将statusCode设置为自己.

protected void service(HttpServletRequest request,
      HttpServletResponse response) throws IOException {
  try {

    // servlet code here, e.g. super.service(request, response);

  } catch (Exception e) {
    // log the error with a timestamp, show the timestamp to the user
    long now = System.currentTimeMillis();
    log("Exception " + now, e);
    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    response.getWriter().println("Guru meditation: " + now);
  }
}
Run Code Online (Sandbox Code Playgroud)

当然,如果你不想要任何内容​​,那么就不要向作者写任何东西,只需设置状态即可.

  • 我认为这个工作的真正原因是因为你已经写入了输出流.我相信如果您只是设置状态并且不向响应写入任何内容,Tomcat将发送405的默认错误响应. (3认同)

rea*_*ice 37

虽然这并没有完全回应关于问题的"不发送任何东西"的陈述,以及Clive Evans回答的浪潮,但我发现在tomcat中你可以使那些冗长冗长的文本远离错误页面而不创建自定义ErrorReportValve.

您可以通过"server.xml"上的2个参数"showReport"和"showServerInfo"来完成此自定义ErrorReportValve:

<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />
Run Code Online (Sandbox Code Playgroud)

链接到官方文档.

在tomcat 7.0.55上为我工作,在tomcat 7.0.47上没有为我工作(我认为是因为以下链接报告的内容http://www.mail-archive.com/users@tomcat.apache.org /msg113856.html)

  • 使用Tomcat 8.优秀的解决方案! (6认同)
  • Tomcat文档说<Valve />元素可以在server.xml中的<Engine />,<Host />或<Context />元素内.对于我来说,将阀门放在<Engine />元素中不起作用,但将其放在单独的<Host />元素中.文档还说Tomcat将任何不匹配的主机名路由到<Host />元素,该元素在<Engine />元素的defaultHost属性中设置.要确保未显示到主机/上下文之外的位置的URL,编译到Tomcat中的错误消息,您需要确保将<Valve />添加到默认<Host />. (3认同)

Cli*_*ans 10

停止Tomcat发送任何错误主体的快速,稍微脏,但简单的方法是针对tomcat主机调用setErrorReportValveClass,并使用自定义错误报告阀来覆盖报告以便不执行任何操作.即:

public class SecureErrorReportValve extends ErrorReportValve {

@Override
protected void report(Request request,Response response,Throwable throwable) {
}

}
Run Code Online (Sandbox Code Playgroud)

并设置为:

  ((StandardHost) tomcat.getHost()).setErrorReportValveClass(yourErrorValveClassName);
Run Code Online (Sandbox Code Playgroud)

如果你想发送你的消息,并且只是认为Tomcat不应该搞乱它,你需要的东西是:

@Override
protected void report(final Request request, final Response response, final Throwable throwable) {
    String message = response.getMessage();
    if (message != null) {
        try {
            response.getWriter().print(message);
            response.finishResponse();
        } catch (IOException e) {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请随意指出您不应该将Tomcat ErrorReportValve重写为包含您可能不希望与外界共享的大量信息的消息的Tomcat ErrorReportValve部分,而是写入只是你的消息.我很好奇...... (2认同)

man*_*nta 9

正如Heikki所说,设置状态而不是sendError()导致Tomcat不接触响应实体/主体/有效负载.

如果您只想发送没有任何实体的响应头,就像我的情况一样,

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
Run Code Online (Sandbox Code Playgroud)

诀窍.有了Content-Length: 0,print()即使使用也无效,如:

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.getWriter().print("this string will be ignored due to the above line");
Run Code Online (Sandbox Code Playgroud)

客户收到如下内容:

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 0
Date: Wed, 28 Sep 2011 08:59:49 GMT
Run Code Online (Sandbox Code Playgroud)

如果要发送一些错误消息,请使用setContentLength()带有消息长度(除零之外),或者可以将其留给服务器


Eri*_*ger 8

虽然它符合Servlet规范,但出于安全考虑,我不希望tomcat或任何其他Servlet容器发送错误详细信息.我也在努力解决这个问题.搜索和尝试后,解决方案可以总结如下:

  1. 正如其他人提到的,不要使用sendError(),setStatus()而是 使用
  2. 像Spring Security这样的框架sendError()虽然使用......
  3. 写了Filter
    一个.将呼叫重定向sendError()setStatus()
    b.最后刷新响应以防止容器进一步修改响应

可以在此处找到执行此操作的小示例servlet过滤器.

  • +1用于指出框架具有预定义的行为并提供示例过滤器,正如我正在使用[Jersey](https://jersey.java.net/) - 让我发现[特定泽西岛属性]( https://jersey.java.net/apidocs/2.5/jersey/org/glassfish/jersey/server/ServerProperties.html#RESPONSE_SET_STATUS_OVER_SEND_ERROR) (3认同)