1

所以我遇到了很多与我类似的问题,我开始明白了,直到我意识到我没有,简而言之,这就是故事:

在身份验证 bean 中,身份验证成功应该会导致访问一些 Web 资源,失败应该“过滤”访问并重定向到当前登录页面。现在,在那个认证 bean 中,我在成功的情况下添加了这一行:

FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(authentificationBean1.AUTH_STATE, "true") ;

AUTH_STATE在 bean 中定义为:

public static final String AUTH_STATE = ""; 

如果失败,我会执行以下操作:

FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(authentificationBean1.AUTH_STATE, null) ;

现在在过滤器(应用于除身份验证页面之外的每个文件的过滤器)中,我的 doFilter 方法如下所示:

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

        if (((HttpServletRequest) request).getSession().getAttribute(authentificationBean1.AUTH_STATE) == null) {
            ((HttpServletResponse) response).sendRedirect("authentification.xhtml");

        } 

        if(((HttpServletRequest) request).getSession().getAttribute(authentificationBean1.AUTH_STATE) != null) {
            ((HttpServletResponse) response).sendRedirect("accueil.xhtml");
        }

    }

我的想法是,如果身份验证顺利,authentificationBean1.AUTH_STATE会话属性将设置为非空值,因此在过滤器测试中我将能够重定向到欢迎页面(accueil.xhtml);如果该属性为空,我们将留在身份验证页面。

品尝整个事情:过滤器似乎工作但太多了,我的意思是即使身份验证测试必须成功,它也不允许我通过欢迎页面。没有过滤器它实际上工作得很好,看起来我错过了一些关于使用带有 JSF 或过滤器的过滤器的东西。

PS:没有应用chain.doFilter,因为我没有另一个过滤器可以调用,但怀疑那里有什么东西。

感谢您的指示。

编辑 :

<filter>
        <filter-name>RestrictionFilter</filter-name>
        <filter-class>beans.RestrictionFilter</filter-class>
</filter>
<filter-mapping>
        <filter-name>RestrictionFilter</filter-name>
        <url-pattern>/faces/accueil.xhtml</url-pattern>
</filter-mapping>
4

1 回答 1

3

您的过滤器在无限循环中运行,每次都重定向到自身。它永远不会继续向 servlet 发出请求。您似乎误解了 HTTP 的工作原理。response.sendRedirect()你基本上是在触发一个全新的 HTTP 请求。这个全新的 HTTP 请求将再次调用过滤器。因此,当您的过滤器匹配条件以重定向到accueil.xhtml时,它将在无限循环中继续重定向到该页面,并且永远不会继续到 servlet 以处理请求。

此外,您还误解了 的含义chain.doFilter()。它没有明确地前进到下一个过滤器。它只是继续请求,就好像没有过滤器一样。链中是否有另一个过滤器完全无关紧要。如果没有过滤器,那么它将最终出现在目标 servlet 中(FacesServlet在您的情况下,由谁负责处理 JSF 页面)。

基本上,流程应该如下:

  • 如果用户未登录,则:
    • 如果当前请求的页面不是authentification.xhtml,则重定向到它。
    • 或者如果当前请求的页面已经是authentification.xhtml,则继续请求。
  • 或者,如果用户已登录,则无论请求的页面如何,都继续请求。

换句话说,应该这样做:

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {    
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    HttpSession session = request.getSession(false);
    String loginURL = request.getContextPath() + "/authentification.xhtml";

    boolean loggedIn = session != null && session.getAttribute(authentificationBean1.AUTH_STATE) != null;
    boolean loginRequest = request.getRequestURI().startsWith(loginURL);
    boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER);

    if (loggedIn || loginRequest || resourceRequest)) {
        chain.doFilter(request, response);
    } else {
        response.sendRedirect(loginURL);
    }
}

请注意,我还添加了对 JSF 资源(通过 包含的 CSS/JS/图像文件<h:outputStylesheet|outputScript|graphicImage>)的检查,否则在显示登录页面时它们也会被阻止。另请注意,此过滤器可以映射到/*而不是仅在单个页面上。

于 2013-05-20T14:13:14.003 回答