【问题标题】:Why request which start with “/WEB-INF” cannot be mapped to a servlet/filter为什么以“/WEB-INF”开头的请求不能映射到servlet/filter
【发布时间】:2012-12-30 18:36:55
【问题描述】:

[上下文] tomcat 7 - java 1.7

大家好;我正面临着陌生人的工作。 在我的 web.xml 文件中,我映射了这样的请求:

web.xml

<web-app>
    <filter>
        <filter-name>filter</filter-name>
        <filter-class>demo.DemoFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>demo.DemoServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

DemoFilter.java(实现过滤器)

@Override
public void doFilter( ServletRequest req, ServletResponse res, FilterChain chain )
        throws IOException, ServletException
{
    try
    {
        chain.doFilter(req, res);
    }
    catch ( Exception e )
    {
        System.err.println("error");
        ((HttpServletResponse) res).setContentType("text/html");
        ((HttpServletResponse) res).setStatus(HttpServletResponse.SC_NOT_FOUND);
        res.getWriter().write("foo");
    }
}

DemoServlet.java(扩展 HttpServlet)

@Override
protected void doGet( HttpServletRequest req, HttpServletResponse resp )
        throws ServletException, IOException
{
    System.err.println(req.getRequestURI());
    throw new RuntimeException("ERROR");
}

[1 = 预期结果] 首先,当我尝试请求“/foo/bar”时,过滤器和 servlet 被调用(页面显示单词“foo”)。控制台结果:

/foo/bar    
error

[2 = Unexpected result] 然后,当我尝试请求“/WEB-INF/foo/bar”时,没有调用任何内容(我的过滤器和我的 servlet 没有被命中),我得到了Tomcat 错误报告:

HTTP Status 404 -

type Status report

message

description The requested resource is not available.
Apache Tomcat/7.0.30

编辑:在这里,我希望得到以下结果:

/WEB-INF/foo/bar    
error

我的目标是使用我的过滤器来处理异常(包括“/WEB-INF”调用)。

  • 为什么以“/WEB-INF/”开头的请求永远不会命中映射在“/*”模式上的过滤器/servlet?
  • 我们如何解决这个问题?

提前致谢!

PS:我想保留我当前的 web.xml 配置(“url-pattern”=“/*”;不使用“error-page”)


编辑我的问题被误解了。我不想在我的“WEB-INF”目录下提供文件访问。我想用我的过滤器和 Servlet (url-pattern='/*') 来处理每个请求,即使请求 URI 以“/WEB-INF/”开头。谢谢!

【问题讨论】:

  • 因为这就是 Servlet 规范中所说的。
  • 为什么要请求 /WEB-INF/foo/bar?你打算在那里放什么需要这种访问权限?
  • @TheZuck 例如创建一个记录用户操作的过滤器。或者在我的情况下,将异常处理集中在过滤器中。
  • 我明白你现在想要做什么,这是一个有趣的问题,但是,由于 WEB-INF 非常特别,答案将非常具体,而且 IMO 不那么有趣。使用您的常规过滤器为其他所有内容提供服务,并在其他 1000 种人们试图渗透您的网站的方式上捕获黑客尝试。访问 WEB-INF(及其配套的 META-INF)只能来自黑客尝试,所以我没有义务以优雅的方式做出回应。
  • tomcat 7 - java 1.7 - 这是犯罪。没有人应该再运行 JDK 7。请升级。

标签: java jakarta-ee tomcat web.xml


【解决方案1】:

这里有一个重大的概念误解。 /WEB-INF 中的资源根本无法公开访问。您提出问题的方式表明并非如此。这个不对。 I believe that you just asked about the concrete problem the wrong way.

根据评论,我了解到您希望在 /WEB-INF 中记录访问的文件以及 404 错误。我您实际上的意思是要在直接请求的资源旁边记录转发、包含和错误的资源。通常情况下,转发和包含的资源确实隐藏在/WEB-INF中,以防止直接访问。

过滤器默认仅在直接请求的资源上调用,而不是在转发和包含的资源上,也不是在错误的资源上,如您的 404 尝试。为此,您需要将适当的 &lt;dispatcher&gt; 条目添加到映射中:

<filter-mapping>
    <filter-name>filter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

(每个都是可选的;REQUEST 是完全不存在时的默认值)

这样,过滤器不仅会拦截直接请求的资源,还会拦截转发、包含和错误的资源。 ERROR 调度程序也将使其启动 404 错误。

【讨论】:

  • 有了这4个调度器的定义,当请求URI以“/WEB-INF/”开头时,我的过滤器仍然没有被调用:(
  • 过滤器肯定被调用了。这更有可能是您的误解。如果出现错误,ERROR_REQUEST_URI 属性仅在doFilter() 调用之后可用。
  • @BalusC : 我又试了一次,还是不行...当我调用 "localhost:8080/WEB-INF/foo" source code 时没有调用任何内容
  • 您的web.xml 声明了哪个servlet 版本? Tomcat 7 是与 Servlet 3.0 兼容的容器,但您在问题中的 &lt;web-app&gt; 根声明是空的。是真实的代码还是过于简化了?
  • 我将&lt;web-app&gt; 版本添加到2.5 以接受&lt;dispatcher&gt; 定义。这是我使用 tomcat7:run 运行的 maven 项目的真实代码
【解决方案2】:

WEB-INF目录是Web应用程序的私有区域,WEB-INF目录下的任何文件都不能通过像你指定的方式指定URL直接从浏览器访问。

Web 容器不会提供此目录的内容。但是,类可以访问此目录的内容,例如您在应用程序的 web.xml 中映射的 servlet。

【讨论】:

  • 虽然同意您的回答(和informatik01's)是正确的,但我想到了一个疑问。如果您将http://myServer/myWebApp/WEB-INF/web.xml 映射到(比如说)myWebApp\publicDirectory\fake-web.xml,则您遵守了限制,但您不需要需要使带有WEB-INF 的URL 无效。我认为这就是这里所说的,因为 OP 将该 URL 映射到 servlet(并且不希望直接检索文件)。
  • 我想说的是:规范中是否还有其他禁止此类 URL 的限制?
  • @PassageOne:当你使用这个 URL 时,它会命中你的过滤器吗?如果是,那么您可以检索请求 URI,从中替换 WEB-INF 并执行重定向。不是一个干净的方法,但你可能想看看它是否有效
  • @Sujay 过滤器和 Servlet 未命中。我得到了一个 Tomcat 错误 :(
【解决方案3】:

如果要限制对某些文件的直接 URL 访问,请将它们放在 WEB-INF 目录下。

从这里引用: http://www.servletworld.com/servlet-tutorials/web-application-directory-structure.html

WEB-INF目录是Web应用程序的私有区域,WEB-INF下的任何文件 不能通过指定从浏览器直接访问目录 网址,例如http://somesite/WEB-INF/someresource.html。 Web 容器将 不提供此目录的内容。不过内容是 WEB-INF 目录可由应用程序中的类访问。 因此,如果您有任何资源,例如 JSP 或 HTML 文档 不希望直接从网络浏览器访问,您应该 放在WEB-INF目录下。

【讨论】:

  • 我不想在我的“WEB-INF”目录下提供文件。我想在“/*”URI 上映射自定义 servlet 或过滤器,即使此 URI 以“WEB-INF”开头。
  • 刚刚尝试使用映射在 /* 上的过滤器,是的 - 尝试访问 /WEB-INF 时仅出现 404 错误并且未触发过滤器。您还希望过滤 /WEB-INF 访问尝试是非常奇特的。但也许@BalusC 知道怎么做,他是这里对 Java EE 和相关技术最有经验的人之一。我个人从来不需要这样的东西,对不起。
  • 感谢您的宝贵时间;至少你终于明白我的问题了;)
【解决方案4】:

发布的两个答案都是正确的,这对于您使用的任何应用程序服务器和 JDK 都是一样的。虽然从 servlet 规范 3.0 web.xml 是可选的,或者您可以使用 web-framgment.xml 来破坏 web.xml。

【讨论】:

    【解决方案5】:

    根据 servlet 规范,来自客户端的任何访问 WEB-INF/ 目录中资源的请求都必须返回一个 SC_NOT_FOUND(404) 响应。请参阅第 10.5 节目录结构。

    https://download.oracle.com/otn-pub/jcp/servlet-3_1-fr-eval-spec/servlet-3_1-final.pdf https://download.oracle.com/otn-pub/jcp/servlet-3.0-fr-eval-oth-JSpec/servlet-3_0-final-spec.pdf

    【讨论】:

      猜你喜欢
      • 2015-04-03
      • 2011-07-13
      • 2010-11-18
      • 2017-01-20
      • 2013-08-14
      • 2016-02-05
      • 2016-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多