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

Ste*_*TNT 1 regex servlets regex-negation servlet-filters

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

所以我Filter必须将它们重定向到错误页面,因为没有会话.

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

所以我需要一个匹配除了/和之外的所有页面的URL模式index.xhtml.

我怎样才能做到这一点?我可以使用正则表达式web.xml吗?

编辑:

看完

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

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

在我的doFilter()方法中,但它仍然处理一切.

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

编辑2:

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

我已将Filter映射到*.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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Bal*_*usC 5

web.xmlURL模式不支持正则表达式.它仅支持通配符前缀(文件夹)和后缀(扩展)等匹配 /faces/**.xhtml.

至于你的具体问题,你显然将索引文件定义为a <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);
}
Run Code Online (Sandbox Code Playgroud)

映射此过滤器/*.请注意,我包含了ResourceHandler.RESOURCE_IDENTIFIER检查以便JSF资源如此<h:outputStylesheet>,<h:outputScript>并且<h:graphicImage>也将被跳过,否则当用户未登录时,您最终会得到没有CSS/JS /图像的索引页面.

请注意,我假设它FacesServlet映射在URL模式上*.xhtml.否则,您需要相应地更改/index.xhtml检查path.