Servlet 过滤器不响应给定的 URL 模式

Posted

技术标签:

【中文标题】Servlet 过滤器不响应给定的 URL 模式【英文标题】:Servlet filter doesn't respond on given URL pattern 【发布时间】:2014-10-20 16:11:53 【问题描述】:

我有一个 JSF Web 应用程序,其中驻留在目录 web 下的所有页面都需要受到保护以防止未经身份验证的使用,即用户应该在会话中访问这些页面。我正在使用过滤器来验证这些页面的会话。这些页面通过以下网址访问:/contextRoot/web/download.xhtml 或 /contextRoot/web/sign/upload.xhtml。而位于 web 目录之外或其他目录中的其他页面不需要通过会话验证过滤器。我的过滤器是这样的:

@WebFilter(filterName = "AuthenticationFilter", urlPatterns="/web/*", dispatcherTypes   = DispatcherType.REQUEST)

public class AuthenticationFilter implements Filter 

    private static final boolean debug = true;
    
    private FilterConfig filterConfig = null;

    public AuthenticationFilter() 
    

    
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException 

        if (debug) 
            log("AuthenticationFilter:doFilter()");
        
        HttpSession session = ((HttpServletRequest) request).getSession(false);
        if (session == null || session.getAttribute("username") == null) 
            System.out.println("Your Session Not Active. You are redirected.");
            //((HttpServletResponse) response).sendRedirect("home.xhtml");
         else 
            System.out.println("Your Session is active. username : " + session.getAttribute("username"));
        

        Throwable problem = null;
        try 
            chain.doFilter(request, response);
         catch (Throwable t) 
            // If an exception is thrown somewhere down the filter chain,
            // we still want to execute our after processing, and then
            // rethrow the problem after that.
            problem = t;
            t.printStackTrace();
        
    

我正在使用 urlPattern /web/* 以便 web 目录中的每个页面都将通过此过滤器。过滤器现在只是打印用于调试的东西。但是每当我访问网页目录或任何其他页面中的页面时,它都不会通过过滤器。我也尝试使用 /faces/web/* 作为 urlPattern 但这也没有用。但是当我把 /* 作为 urlPattern 时,每个访问的页面都会通过过滤器。 我以http://localhost:8080/CodesignWebApp/faces/web/sign/SelectServer.xhtml http://localhost:8080/CodesignWebApp/faces/web/sign/FileUpload.xhtml?signmethod=MICROSOFT

身份访问页面

我怀疑 urlPattern 有问题。

【问题讨论】:

“我的页面其实不是直接在web下的,它们就像web/sign/sign.xhtml” 这个很模糊,很混乱。请详细说明那部分。更好的是,让我们从头开始:请将您实际使用的网址复制粘贴到您想要调用此过滤器的网络浏览器的地址栏中。 添加了页面的确切 URL。 好的。那么,/faces/web/* 就是您需要的那个。这到底是怎么失败的?你确定你正在运行你认为你正在运行的代码吗? (更改 URL 模式后重新构建、重新部署等,即在启动期间仅初始化一次)。更好的选择是完全摆脱古老的 JSF 1.0 样式 /faces/* 路径映射,并用 *.xhtml 替换它。 【参考方案1】:

我正在访问页面

http://localhost:8080/CodesignWebApp/faces/web/sign/SelectServer.xhtmlhttp://localhost:8080/CodesignWebApp/faces/web/sign/FileUpload.xhtml

@WebFilter(和@WebServlet)的 URL 模式必须与您在浏览器地址栏中看到的那些 URL 完全匹配(因此不是您在服务器中实际拥有的磁盘文件系统路径侧面;它也被称为“URL 模式”,而不是“文件模式”或其他)。

所以,总而言之,只要/CodesignWebApp 是 webapp 的上下文根,就应该这样做:

@WebFilter("/faces/web/*")
public class AuthenticationFilter implements Filter 
    // ...

(过滤器名称不相关,您指定的请求调度程序方法已经是默认值)

另一种选择是完全摆脱古老的 JSF 1.0 样式 /faces/* 映射,并将其替换为 JSF 2.0 样式 *.xhtml 映射。您不希望最终用户在从 URL 中删除 /faces 部分时看到原始 JSF 源代码,对吧?

<servlet-mapping>
    <servlet-name>facesServlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

这样你就可以访问页面如下:

http://localhost:8080/CodesignWebApp/web/sign/SelectServer.xhtmlhttp://localhost:8080/CodesignWebApp/web/sign/FileUpload.xhtml

并将过滤器映射如下:

@WebFilter("/web/*")
public class AuthenticationFilter implements Filter 
    // ...

另见:

JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?

【讨论】:

以上是关于Servlet 过滤器不响应给定的 URL 模式的主要内容,如果未能解决你的问题,请参考以下文章

透过源码学习设计模式1—Servlet Filter和责任链模式

在不使用过滤器和包装器的情况下删除 URL 中的 JSESSIONID

从 servlet 过滤器中检索 REST URL 模式

《Head First Servlets & JSP》-13-过滤器和包装器

过滤器映射 URL 模式 *.action 不起作用 struts2

如何在 Jetty 中的 /* 上映射 servlet 过滤器?