【问题标题】:Tomcat serving static content提供静态内容的 Tomcat
【发布时间】:2011-04-18 20:41:20
【问题描述】:

我有一个 Spring 应用程序,我想知道提供静态内容的最佳方式。我尝试了以下方法:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

这是可行的,但 DefaultServlet 的行为意味着任何形式为 /static/PATH 的请求都会为来自 webapp/PATH 的文件提供服务。这暴露了一个巨大的漏洞,允许使用 URL 显示敏感信息,例如:http://localhost/app/static/META-INF/context.xml

常见的解决方案是什么?我应该移动敏感文件吗?编写我自己的 DefaultServlet?还是有更好的方式来提供静态内容?

【问题讨论】:

  • 你的context没有问题吗,比如docBase?

标签: java spring tomcat servlets


【解决方案1】:

你测试了吗?根据 Servlet 规范,/META-INF/WEB-INF 文件夹应该是公共的不可访问。客户端应该为此获得 404。否则会是 DefaultServlet 中的一个错误。

这是Servlet 2.5 spec的摘录:

SRV.9.5 目录结构

...另外,任何 客户端访问WEB-INF/目录中资源的请求必须是 返回 SC_NOT_FOUND(404) 响应。

SRV.9.6 Web 应用存档文件

...此外,任何访问 META-INF 目录中的资源必须返回 SC_NOT_FOUND(404) 回应。


更新:好的,我收回我的话。我可以在最新的 Tomcat 6 和 7 上重现这一点。这绝对是 DefaultServlet 中的一个错误。它在 Glassfish 3.0.1 上运行良好(返回 404)。


更新 2:我已将此事报告给 Tomcat 人员issue 50026


更新 3:其中一位 Tomcat 人员回复如下:

我想这是WONTFIX

servlet 引擎保护 web 中的 WEB-INFMETA-INF 路径 应用程序(工作正常),而不是任意名称下的文件 路径。

这里实际发生的是您正在配置一个通用文件 服务 servlet 以在不同的路径下安装整个 Web 应用程序 - 相当于配置 Apache 做同样的事情。除了那个 DefaultServlet 不是通用文件服务器 - 它旨在映射 到/,除了从网络上提供文件之外,您无法将其配置为执行任何操作 应用程序目录。

我猜您正在尝试解决映射引入的问题 /* 的另一个 servlet,它基本上是在尝试解决 servlet 引擎工作。 How to access static resources when mapping a global front controller servlet on /* 如果这是你正在尝试的,有一个更好的方法来处理事情的例子 去做。

在 Tomcat 中重新挂载 DefaultServlet 的建议似乎一直存在 Tomcat 已经存在,所以也许我们需要锁定它(所以人们不能 意外创建不安全的配置)或支持安装特定 目录(在 Web 应用程序内部或外部),如果访问 在任何情况下映射到子路径时的根资源。


更新 4:他们最终修复了它:

针对 DefaultServlet 和 WebdavServlet 的修复已在 7.0.x 中提交(将在 7.0.4+)并建议用于 6.0.x。 需要检查 5.5.x 并查看是否也需要反向移植。

【讨论】:

  • 我做了测试,我可以清楚地看到我的 context.xml,里面有我的数据库密码。
  • 要么你把 WEB-INFMETA-INF 文件夹放在了错误的位置(它们必须放在 webcontent 根目录中,而不是放在像 /static 这样的子文件夹中),或者存在错误使用的 Tomcat 版本。
  • Tomcat 6 实际上是这样工作的。甚至 Spring 的 Petclinic 样本也很脆弱 src.springframework.org/svn/spring-samples/petclinic/trunk 哇,哇。
  • 刚得到一个新的 Tomcat 6,一个全新的 Eclipse 中的动态 Web 项目,并在web.xml 中添加了以下内容,我可以访问 META-INF:默认/static/*
  • 我收回我的话,我可以重现这个。这太惊人了。
【解决方案2】:

有几种更好的方式来提供静态内容。

传统方法是使用UrlRewriteFilter 重新映射网址,如下所示:

web.xml:

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
...
<servlet-mapping>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <url-pattern>/app/*</url-pattern>
</servlet-mapping>

urlrewrite.xml:

<urlrewrite default-match-type="wildcard">
    <rule>
        <from>/images/**</from>
        <to>/images/$1</to>
    </rule>
    <rule>
        <from>/scripts/**</from>
        <to>/scripts/$1</to>
    </rule>
    <rule>
        <from>/styles/**</from>
        <to>/styles/$1</to>
    </rule>
    <rule>
        <from>/**</from>
        <to>/app/$1</to>
    </rule>
</urlrewrite>

这种方法可以在大多数 Spring 示例中看到。


Spring 3.0.1 引入了更新的方法 - 它可以通过DispatcherServlet 提供静态内容。它可以使用 Spring 配置文件中的&lt;mvc:resource&gt; 元素进行配置。在 Spring 3.0.4 中,它通过支持多个位置和缓存控制选项进行了扩展,请参阅15.12.4 mvc:resources

【讨论】:

  • @BalusC:这两种描述的方法都解决了这个问题——前者通过将/*重新映射到/app/*并明确排除,后者——通过映射到/DispatcherServlet提供静态内容。
  • 根据我的经验,需要 Spring 3.0.4 才能识别 &lt;mvc:resource&gt; 标签(不是 3.0.1)
【解决方案3】:

WEB-INFMETA-INF 是私人文件夹。客户端必须为此收到 404 错误。由于META_INF的内容无法直接访问,否则将所有敏感文件移至WEB_INF

【讨论】:

    猜你喜欢
    • 2015-06-20
    • 2011-02-01
    • 2018-12-25
    • 2011-09-15
    • 2016-01-18
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    相关资源
    最近更新 更多