给Servlet Filter提供多个URL模式

90

我在我的JSF应用程序中使用了一个Servlet过滤器。 我的应用程序有三组Web页面,我想在我的Servlet过滤器中检查这些页面的身份验证:

我的文件夹

/Admin/ *.xhtml

/Supervisor/*.xhtml
/Employee/*.xhtml

我正在编写web.xml文件,内容如下:

<filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>com.ems.admin.servlet.LoginFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/Employee/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/Admin/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/Supervisor/*</url-pattern>
</filter-mapping>

但是类似于请求

http://localhost:8080/EMS2/faces/Html/Admin/Upload.xhtml

未进入筛选器。

我需要为这三个文件夹提供安全保障。

如何解决这个问题?

2个回答

153
如果一个URL模式以/开头,那么它是相对于上下文根的。 /Admin/* URL模式只能匹配http://localhost:8080/EMS2/Admin/* 上的页面(假设/EMS2是上下文路径),但是实际上您将它们放在了http://localhost:8080/EMS2/faces/Html/Admin/*上,因此您的URL模式从未匹配。

您还需要像这样在URL模式前加上/faces/Html

<url-pattern>/faces/Html/Admin/*</url-pattern>
你也可以重新配置你的Web项目结构/配置,以便在URL中摆脱/faces/Html路径,这样你只需通过例如http://localhost:8080/EMS2/Admin/Upload.xhtml打开页面即可。
你的过滤器映射语法全部正确。然而,指定多个URL模式的更简单方法是只使用一个<filter-mapping>,并带有多个<url-pattern>条目。
<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/faces/Html/Employee/*</url-pattern>
    <url-pattern>/faces/Html/Admin/*</url-pattern>
    <url-pattern>/faces/Html/Supervisor/*</url-pattern>
</filter-mapping>

4
据我所见,不允许使用多个url-pattern元素,而且其效果不如预期。 - Sebastian vom Meer
18
@SebastianG:你的具体问题是由其他地方引起的。请注意,对于多个<url-pattern>元素的支持是在Servlet 2.5中引入的(Java EE 5的一部分,发布了近7年)。也许你正在处理一只史前巨兽,或者你有严重的配置问题,导致你的容器以回退模式运行,匹配Servlet 2.4或更早版本,从而失去所有Servlet 2.5的功能。 - BalusC
17
请注意,如果多个<filter-mapping>匹配相同的资源,例如一个使用/*,另一个使用/foo.xhtml作为url-pattern,则会执行相同的过滤器两次。我在JBoss AS 7.1上遇到了这种行为。 - Sebastian Hoffmann
2
@Paranaix:这确实是指定的行为。也许你正在混淆与servlet映射,它确实只会执行最匹配URL模式的servlet。 - BalusC
https://dev59.com/42nWa4cB1Zd3GeqP1otU - mvmn

22

如果您使用注释方法来定义过滤器(而不是在 web.xml 中定义),则可以通过在 @WebFilter 注释中放置一个映射数组来实现:

/**
 * Filter implementation class LoginFilter
 */
@WebFilter(urlPatterns = { "/faces/Html/Employee","/faces/Html/Admin", "/faces/Html/Supervisor"})
public class LoginFilter implements Filter {
    ...

顺带一提,使用 servlet 注解的 servlet 也可以使用同样的方法:

/**
 * Servlet implementation class LoginServlet
 */
@WebServlet({"/faces/Html/Employee", "/faces/Html/Admin", "/faces/Html/Supervisor"})
public class LoginServlet extends HttpServlet {
    ...

8
即使只是一个示例,扩展Filter而不是HttpServlet会更好吗? - alexander
一个过滤器可以针对不同的servlet URL模式执行。你不能用一个servlet替换一个过滤器。 - Ravindra Gullapalli
他想要一个过滤器行为,而不是servlet行为。我猜他已经将这些URL映射到了servlet上。 - Антон Антонов

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接