在索引之外的所有页面上使用Servlet过滤器

时间:2012-05-22 19:23:31

标签: regex servlets servlet-filters regex-negation

我正在尝试使用Filter强制我的用户登录,如果他们想要访问某些页面。

所以我的Filter必须将它们重定向到没有会话的错误页面。

但我不希望在访问index.html时发生这种情况,因为他们可以在索引页面登录。

所以我需要一个匹配/index.xhtml之外的所有网页的网址格式。

我该怎么做?我可以在web.xml中使用正则表达式吗?

编辑:

阅读this

我以为我可以做类似的事情:

if (!req.getRequestURI().matches("((!?index)(.*)\\.xhtml)|((.*)\\.(png|gif|jpg|css|js(\\.xhtml)?))"))

在我的doFilter()方法中,但它仍处理所有内容。

我确信正则表达式有效,因为我已经在线测试了它并且它匹配了不需要过滤的文件,但即使对于排除的文件也会执行if的内容!

编辑2:

我正在尝试一种新的方式。

我已将过滤器映射到*.xhtml中的web.xml,因此我不需要使用上面的正则表达式排除css,图片和javascript。

这是新代码(进入doFilter()

if (req.getRequestURI().contains("index")) {
    chain.doFilter(request, response);
} else {
    if (!userManager.isLogged()) {
        request.getRequestDispatcher("error.xhtml").forward(request, response);
    } else {
        chain.doFilter(request, response);
    }
}

但它仍然没有,因为它在每个页面上调用chain.doFilter()(在外部if中)。

如何排除我的索引页面被过滤?

1 个答案:

答案 0 :(得分:5)

web.xml网址格式不支持正则表达式。它仅支持通配符前缀(文件夹)和后缀(扩展名)匹配,如/faces/**.xhtml

对于您的具体问题,您显然将索引文件定义为<welcome-file>并按/打开它。这样request.getRequestURI()将等于/contextpath/,而不是/contextpath/index.xhtml。调试request.getRequestURI()以了解过滤器实际检索的内容。

我建议改写:

String path = request.getRequestURI().substring(request.getContextPath().length());

if (userManager.isLogged() || path.equals("/") || path.equals("/index.xhtml") || path.startsWith(ResourceHandler.RESOURCE_IDENTIFIER)) {
    chain.doFilter(request, response);
} else {
    request.getRequestDispatcher("/WEB-INF/error.xhtml").forward(request, response);
}

/*上映射此过滤器。请注意,我添加了ResourceHandler.RESOURCE_IDENTIFIER检查,以便也可以跳过<h:outputStylesheet><h:outputScript><h:graphicImage>等JSF资源,否则最终会得到一个没有CSS / JS的索引页面/用户未登录时的图像。

请注意,我假设FacesServlet映射到*.xhtml的网址格式。否则,您需要相应地更改对/index.xhtml的{​​{1}}检查。