web.xml - Java Servlet 过滤器 - 在处理 JSP 页面之前未运行(在 Tomcat 上)

Posted

技术标签:

【中文标题】web.xml - Java Servlet 过滤器 - 在处理 JSP 页面之前未运行(在 Tomcat 上)【英文标题】:web.xml - Java Servlet Filters - Not being run before processing the JSP page (on Tomcat) 【发布时间】:2010-12-15 19:03:45 【问题描述】:

我对 Servlet 过滤器相当陌生,基本上加入了一个使用它们的项目,并在 web.xml 文件中添加了一个额外的过滤器(部署在 Tomcat 5.5 上)。

我有 95% 的把握在某些时候它工作正常,但现在在调试时,如果我将断点放在我试图查看的 JSP 页面的顶部 (login.jsp),它是模板页面 (page.jsp)并在配置的过滤器的doFilter() 方法中;它贯穿整个login.jsp 页面(从上到下),然后是page.jsp 并开始处理过滤器。

我需要它首先运行过滤器,因为其中一个决定了页面应该显示的语言(检查 cookie、数据库设置和浏览器设置),然后应该应用于login.jsp

有没有人对可能出现的问题提出任何建议?

我可以发布很多代码,但我不相信它们会有任何用处,因为它们都以错误的顺序工作。

来自 web.xml 的片段:

<web-app>
...
<filter>
        <filter-name>SetSecurityContextFilter</filter-name>
        <filter-class>
            com.section2.SecurityContextServletFilter
        </filter-class>
    </filter>

<filter>
    <filter-name>SetLocaleFilter</filter-name>
    <filter-class>
        com.section2.locale.LocaleServletFilter
    </filter-class>
</filter>

<filter>
    <filter-name>trinidad</filter-name>
    <filter-class>org.apache.myfaces.trinidad.webapp.TrinidadFilter</filter-class>
</filter>

<filter>
    <filter-name>ActiveUserFilter</filter-name>
    <filter-class>com.section2.ActiveUserFilter</filter-class>
</filter>

    <filter-mapping>
        <filter-name>trinidad</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>

    <filter-mapping>
        <filter-name>SetSecurityContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>SetLocaleFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>ActiveUserFilter</filter-name>
        <url-pattern>/pages/section2/user/*</url-pattern>
    </filter-mapping>

...
</web-app>

提前致谢。

【问题讨论】:

您看过java.sun.com/products/servlet/Filters.html 和tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/… 吗?在不知道自己在做什么的情况下,很难想象出了什么问题。您是否尝试过另一个 servlet 容器,例如 jetty? 【参考方案1】:

一个明显的错误是在特立尼达过滤器映射中。它不应该有一个 servlet-name,而是一个 url-pattern。

【讨论】:

完全有效。这仅意味着特定过滤器与相关的 servlet 耦合,因此仅在相同的 url-pattern 上调用。【参考方案2】:

Filter 代码是如何组织的?您是否可能先调用FilterChain#doFilter(),然后才执行所需的逻辑?

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
    // Any code here will be executed BEFORE passing request through JSP/Servlet.
    chain.doFilter(request, response);
    // Any code here will be executed AFTER passing request through JSP/Servlet.

【讨论】:

【参考方案3】:

感谢您的回复 - 我现在已经完全理解了这个问题......它只发生在 login.jsp 页面,没有其他页面。在我的例子中,login .jsp 页面是一个特例,因为它通常被视为重定向的结果。

web.xml

<login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/login.jsp?error=true</form-error-page>
        </form-login-config>
    </login-config>

因此我认为过滤器没有按通常的顺序命中!从登录页面添加了一个调用来执行过滤器所做的事情,一切都很好。

再次感谢。

【讨论】:

【参考方案4】:

没有为 login.jsp 调用过滤器的原因是 Tomcat 对规范的解释是身份验证是容器的一部分,而不是 webapp 的一部分,因此发生在过滤器的角色之外。因此过滤器不适用于登录页面(在本例中为 login.jsp)或 j_security_check。

ref:https://issues.apache.org/bugzilla/show_bug.cgi?id=21795 - 标题仅引用 j_security_check,但讨论涵盖了整个基于表单的身份验证机制。

【讨论】:

【参考方案5】:

我写的时候也遇到了同样的问题:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
   if(...) 
      response.sendRedirect(url);
   
   chain.doFilter(request, response);

改为

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
   if(...) 
      response.sendRedirect(url);
      return;
   
   chain.doFilter(request, response);

【讨论】:

以上是关于web.xml - Java Servlet 过滤器 - 在处理 JSP 页面之前未运行(在 Tomcat 上)的主要内容,如果未能解决你的问题,请参考以下文章

java 过滤器必须要配置在web.xml中吗?

Filter过滤器

servlet 过滤器是不是必须在 web.xml 文件中指定?

WEB-INF/web.xml 和 conf/web.xml 中定义的 servlet 过滤器的实际执行顺序是啥

Servlet和JSP中的过滤器都是Java类

java-servlet过滤器和监听