Http错误码状态从405变为401spring boot 2和jetty

问题描述

感谢您抽出宝贵时间调查此问题。我一直在研究 spring boot 2 应用程序,并且我添加一个自定义过滤器(disabledHttpMethodFilter extends OncePerRequestFilter 实现 Ordered)以不允许 TRACE 和 OPTIONS 方法调用。我抛出错误(SC_METHOD_NOT_ALLOWED = 405)。过滤器似乎正在工作,并且不允许 TRACE 和 OPTIONS 调用,但存在一些问题,http 状态代码从 405 更改为 401。我已多次调试该问题,但找不到其背后的根本原因。 我正在附上调试中的屏幕截图。处理程序和调度程序方法堆栈中的错误代码更改。

在下面的屏幕中可以看到,过滤器类状态代码 405 被抛出。

enter image description here

没有中间过滤器/处理程序造成任何伤害,直到 HttpChannel 类,事情才会顺利。

enter image description here

从这个类代码到 ErrorHandler(我跳过了很多类和他们的屏幕截图。只是想展示中间阶段。仍然是 405 代码

enter image description here

然后在句柄/调度方法之一中,它从 405 更改为 401。

enter image description here

请让我知道那里可能有什么问题。我有一个并行应用程序,其中相同的过滤器工作正常。我已经并行调试了两个应用程序,但我在方法堆栈中迷失了方向。再次感谢您。

解决方法

如果您到达 org.springframework.boot.web.embedded.JettyEmbeddedErrorHandler,那么在到达该代码之前知道您的响应已被重置很重要。

此行为符合 Servlet 规范。

这意味着所有响应头、缓冲区和值都重置为默认值(一个值得注意的例外是响应中跟踪的 java.servlet.http.Cookie 对象)。

一般 Servlet 和/或 Jetty 建议。

首先,默认情况下 TRACE 在所有 WebApp 上都是禁用的,但这是 Spring,所有赌注都已关闭(因为它认为它比容器更了解)。

接下来,在 Servlet 规范中通过约束而不是过滤器来禁用 HTTP 方法。 (就像禁用的TRACE方法一样)

  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Disable TRACE</web-resource-name>
      <url-pattern>/</url-pattern>
      <http-method>TRACE</http-method>
    </web-resource-collection>
    <auth-constraint/>
  </security-constraint>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Enable everything but TRACE</web-resource-name>
      <url-pattern>/</url-pattern>
      <http-method-omission>TRACE</http-method-omission>
    </web-resource-collection>
  </security-constraint>

DisabledHttpMethodFilter的建议。

你的 DisabledHttpMethodFilter 应该避免使用 OncePerRequestFilter,它不适合终端行为(你不想在 Spring 中处理更多的事情)。由于使用 Spring 过滤器作为基础,Spring 中的过滤器堆栈将基本上取消您的努力。

Ordered 行为可以确保您的 Filter 位于正确的位置,但即便如此,最终也不需要成功。

如果您的 DisabledHttpMethodFilter 使用 HttpServletResponse.sendError(),那么您应该确保在您的 Spring 应用程序中对响应代码 405 进行自定义错误处理,而该处理基本上什么都不做。 (防止spring和jetty破坏你的努力)

如果您的 DisabledHttpMethodFilter 使用 HttpServletResponse.setStatus() 并在不调用过滤器链的情况下返回,那么您就无事可做(但很容易得到可能与您的过滤器链冲突的额外响应标头)意图。就像在状态代码的响应中缓存不合适的头一样)

DisabledHttpMethodFilter 的更好方法是抛出自定义异常,例如 MethodDisabledException 和使用 spring 和/或 Jetty 注册的自定义错误处理,用于该异常,只需将状态代码设置为405. 这允许响应重置发生(一件好事!),并最大限度地减少执行和更改您的意图的其他 Spring 调度行为。