自行开发的身份验证过滤器不显示欢迎页面

时间:2013-05-20 10:28:40

标签: security jsf login servlet-filters

所以我遇到了类似于我的一些麻烦的问题,直到我意识到我没有,直到这就是故事:

在验证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 会话attribut将设置为非空的内容,因此在过滤器测试中我将能够重定向到欢迎页面( accueil.xhtml);如果该attribut为null,我们将保留在authentification页面中。

品尝整个事情:过滤器似乎工作但过多,我的意思是即使验证测试必须成功,它也不允许我传递到欢迎页面。它实际上没有过滤器工作正常,看起来我错过了使用JSF或过滤器的过滤器。

P.S:没有应用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>

1 个答案:

答案 0 :(得分: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资源(通过<h:outputStylesheet|outputScript|graphicImage>包含的CSS / JS /图像文件)的检查,否则在显示登录页面时也会阻止它们。另请注意,此过滤器可以映射到/*,而不能映射到单个页面。