Struts 相对路径在 7.0.78 中变平但在 7.0.79 中没有,打破了 isNormalized

Struts relative path flattened in 7.0.78 but not in 7.0.79, breaking isNormalized

我们在 Spring 启动应用程序中从 Struts 2 操作返回 @Result,它指定包含相对路径的位置,以便引用 jsp应用程序其余部分根目录的同级目录。

@Result(name = "foo", location = "../../cat/bar.jsp")

这适用于 Tomcat 7.0.78,到达 StrictHttpFirewall.getFirewalledRequest 为:

ApplicationHttpRequest.requestURI = "rootParent/cat/bar.jsp"

在 Tomcat 7.0.79+ 中,这种扁平化不再发生,当请求到达 StrictHttpFirewall 以检查 url 规范化时,它爆炸了,因为它到达:

ApplicationHttpRequest.requestURI = "rootParent/root/WEB-INF/../../cat/bar.jsp"

我搜索了 Apache 7 changelog and security fixes 以查看是否有任何可能导致这种情况发生的原因,但一无所获。我试过调整 useRelativeRedirects 上下文 属性,但它似乎没有任何效果。在调试中通过过滤器链拉出我的头发。任何帮助将不胜感激!

所有这些相对路径经常出现在安全漏洞工具中,因此它们通常不是一个好主意,您可能应该停止使用它们。

就是说,如果您像骡子一样固执,您仍然可以使用它们,只是不在注释本身内,但是您可以使用 static 变量来实现相同的目的,前提是这些文件存在作为某处的资源:

FooBar.class.getClassLoader().getResource('../../cat/bar.jsp')

我想通了问题并找到了解决方案。

问题是 this commit 在 7.0.78 和 7.0.79 之间更改了 org.apache.catalina.core.ApplicationContext.getRequestDispatcher 的行为。以前,提供的 URL 在附加到上下文路径之前进行了规范化。在 7.0.79 及更高版本中,不再使用规范化版本。

没有更改此行为的设置,但我想出了如何通过修改 Struts 传入的位置来解决问题。当请求到达 ApplicationContext 时,struts 已经将上下文和 url 合并到一个位置,但我们可以覆盖 Request 注释中的上下文部分。它对其他所有内容都使用 "WEB-INF/content/" + "%{url}",所以我将其更改为 "%{url}".

之前,结果为 "WEB-INF/content/../../bar.jsp"

@Result(name = "foo", location = "../../bar.jsp")

之后,结果为 "bar.jsp"

@Result(name = "foo", location = "bar.jsp", params = {"location", "%{url}"})