问题描述
感谢您抽出宝贵时间调查此问题。我一直在研究 spring boot 2 应用程序,并且我添加了一个自定义过滤器(disabledHttpMethodFilter extends OncePerRequestFilter 实现 Ordered)以不允许 TRACE 和 OPTIONS 方法调用。我抛出错误(SC_METHOD_NOT_ALLOWED = 405)。过滤器似乎正在工作,并且不允许 TRACE 和 OPTIONS 调用,但存在一些问题,http 状态代码从 405 更改为 401。我已多次调试该问题,但找不到其背后的根本原因。 我正在附上调试中的屏幕截图。处理程序和调度程序方法堆栈中的错误代码更改。
在下面的屏幕中可以看到,过滤器类状态代码 405 被抛出。
没有中间过滤器/处理程序造成任何伤害,直到 HttpChannel 类,事情才会顺利。
从这个类代码到 ErrorHandler(我跳过了很多类和他们的屏幕截图。只是想展示中间阶段。仍然是 405 代码)
然后在句柄/调度方法之一中,它从 405 更改为 401。
请让我知道那里可能有什么问题。我有一个并行应用程序,其中相同的过滤器工作正常。我已经并行调试了两个应用程序,但我在方法堆栈中迷失了方向。再次感谢您。
解决方法
如果您到达 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 调度行为。