在JSF项目中使用授权过滤器进行自定义身份验证

4

我在我的应用程序中嵌入了登录/退出功能,但过滤器可能没有起作用,因为我在浏览器地址栏中指向它们后仍然可以看到已经登出的页面。这是我的登录操作:

this.currentUser = new User();  // initiate currentUser
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.getApplication().createValueBinding("#{" + Constants.VISIT_KEY_SCOPE +
Constants.VISIT_KEY + "}").setValue(facesContext, currentUser);
FacesUtils.putIntoSession(Constants.VISIT_KEY, currentUser);

注销操作:

FacesContext facesContext = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)facesContext.getExternalContext().getSession(false);
session.removeAttribute(Constants.VISIT_KEY_SCOPE + Constants.VISIT_KEY);

 if (session != null)
    {
     session.invalidate();
    }

常量类:

public class Constants
{
  // Backing bean keys
 public final static String VISIT_KEY_SCOPE = "sessionScope.";
 public final static String VISIT_KEY = "currentUser";

 // Model object keys
 public final static String PROJECT_COORDINATOR_SCOPE = "applicationScope.";


  public final static String ORIGINAL_VIEW_SCOPE = "sessionScope";
  public final static String ORIGINAL_VIEW_KEY = "originalTreeId";
  }

web.xml文件:

 <filter>
 <filter-name>AuthorizationFilter</filter-name>
 <filter-class>org.AuthorizationFilter.AuthorizationFilter</filter-class>
 </filter>
 <filter-mapping>
 <filter-name>AuthorizationFilter</filter-name>
 <url-pattern>/faces/pages/*</url-pattern>
 </filter-mapping>

最后,授权过滤器如下:

public class AuthorizationFilter implements Filter
{
 FilterConfig config = null;
 ServletContext servletContext = null;

 public AuthorizationFilter()
 {
 }

 public void init(FilterConfig filterConfig) throws ServletException
 {
  config = filterConfig;
  servletContext = config.getServletContext();
  }

  public void doFilter(ServletRequest request, ServletResponse response,
                   FilterChain chain) throws IOException, ServletException
     {
       HttpServletRequest httpRequest = (HttpServletRequest)request;
       HttpServletResponse httpResponse = (HttpServletResponse)response;
       HttpSession session = httpRequest.getSession();

       User currentUser = (User)session.getAttribute("currentUser");

    if (session  == null || currentUser == null || currentUser.getUserName() == null)
     {
      session.setAttribute(Constants.ORIGINAL_VIEW_KEY, httpRequest.getPathInfo());
      httpResponse.sendRedirect(httpRequest.getContextPath() +  "/faces/pages  
       /login.jsp");
      }
     else
        {
         session.removeAttribute(Constants.ORIGINAL_VIEW_KEY);
         chain.doFilter(request, response);
         } 

         }

          public void destroy()
          {
           }
           }

感谢您的耐心和帮助。
1个回答

3
您需要告诉浏览器不要缓存受限页面,以便检查用户是否已登录。否则,浏览器将只从缓存中显示页面,从而永远不会调用您的过滤器。您可以通过在过滤器调用FilterChain#doFilter()之前,在else块中添加以下行来实现:
httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
httpResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0.
httpResponse.setDateHeader("Expires", 0); // Proxies.

与具体问题无关,您的代码存在一些缺陷:

  1. 在您的注销操作中,getSession() 中传入了 false,因此 session.removeAttribute() 可能会抛出 NullPointerException。由于您要调用 session.invalidate(),因此这行代码是多余的。请将其删除。

  2. 在您的过滤器中,request.getSession() 永远不会返回 null,因为您没有传递 false。因此,session == null 是多余的,或者您必须添加 false


1
嗨BalusC。感谢您的回复。我已经添加了“缓存清除”的代码,并解决了您提到的1和2号问题。应用程序没有抛出任何错误,但是当在浏览器中输入页面地址时,页面仍然会显示出来。有任何想法在哪里查找问题? - Jamal Khattak

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