如何在JSF中实现loginfilter?

我想阻止某些页面的访问,即使用户知道某些页面的url。 例如,/ /localhost:8080/user/home.xhtml (需要先login)如果没有logging,则redirect到/index.xhtml

JSF中如何做到这一点? 我在谷歌阅读需要一个filter,但我不知道如何做到这一点。

您需要实现javax.servlet.Filter类,在doFilter()方法中doFilter()所需的工作,并将其映射到覆盖受限制页面的URL模式/user/* maybe? 在doFilter()内部,你应该以某种方式检查会话中login用户的存在。 此外,您还需要考虑JSF ajax和资源请求。 JSF ajax请求需要一个特殊的XML响应来让JavaScript执行redirect。 需要跳过JSF资源请求,否则您的login页面将不再有任何CSS / JS /图像。

假设您有一个/login.xhtml页面,它通过externalContext.getSessionMap().put("user", user)将login用户存储在JSF托pipebean中,那么可以通过session.getAttribute("user")通常的方式如下所示:

 @WebFilter("/user/*") public class AuthorizationFilter implements Filter { private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<partial-response><redirect url=\"%s\"></redirect></partial-response>"; @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() + "/login.xhtml"; boolean loggedIn = (session != null) && (session.getAttribute("user") != null); boolean loginRequest = request.getRequestURI().equals(loginURL); boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/"); boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request")); if (loggedIn || loginRequest || resourceRequest) { if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882 response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1. response.setHeader("Pragma", "no-cache"); // HTTP 1.0. response.setDateHeader("Expires", 0); // Proxies. } chain.doFilter(request, response); // So, just continue request. } else if (ajaxRequest) { response.setContentType("text/xml"); response.setCharacterEncoding("UTF-8"); response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect. } else { response.sendRedirect(loginURL); // So, just perform standard synchronous redirect. } } // You need to override init() and destroy() as well, but they can be kept empty. } 

此外,该filter还禁用了受保护页面上的浏览器caching,因此浏览器后退button不会再显示出来。

如果您碰巧使用JSF实用程序库OmniFaces ,上面的代码可能会减less,如下所示:

 @WebFilter("/user/*") public class AuthorizationFilter extends HttpFilter { @Override public void doFilter(HttpServletRequest request, HttpServletResponse response, HttpSession session, FilterChain chain) throws ServletException, IOException { String loginURL = request.getContextPath() + "/login.xhtml"; boolean loggedIn = (session != null) && (session.getAttribute("user") != null); boolean loginRequest = request.getRequestURI().equals(loginURL); boolean resourceRequest = Servlets.isFacesResourceRequest(request); if (loggedIn || loginRequest || resourceRequest) { if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882 Servlets.setNoCacheHeaders(response); } chain.doFilter(request, response); // So, just continue request. } else { Servlets.facesRedirect(request, response, loginURL); } } } 

也可以看看:

  • 我们的Servletfilterwiki页面
  • 如何处理数据库中用户的authentication/授权?
  • 使用JSF 2.0 / Facelets,有没有办法将全局侦听器附加到所有的AJAX调用?
  • 避免JSF Web应用程序上的后退button
  • JSF:如何控制JSF中的访问和权限?