Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How implement a login filter in JSF?

I would like to block the access of some page even if the user knows the url of some pages. For example, /localhost:8080/user/home.xhtml (need to do the login first) if not logged then redirect to /index.xhtml.

How do that in JSF ? I read in the Google that's needed a filter, but I don't know how to do that.

like image 587
Valter Silva Avatar asked Dec 12 '11 19:12

Valter Silva


1 Answers

You need to implement the javax.servlet.Filter class, do the desired job in doFilter() method and map it on an URL pattern covering the restricted pages, /user/* maybe? Inside the doFilter() you should check the presence of the logged-in user in the session somehow. Further you also need to take JSF ajax and resource requests into account. JSF ajax requests require a special XML response to let JavaScript perform a redirect. JSF resource requests need to be skipped otherwise your login page won't have any CSS/JS/images anymore.

Assuming that you've a /login.xhtml page which stores the logged-in user in a JSF managed bean via externalContext.getSessionMap().put("user", user), then you could get it via session.getAttribute("user") the usual way like below:

@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. } 

Additionally, the filter also disabled browser cache on secured page, so the browser back button won't show up them anymore.

In case you happen to use JSF utility library OmniFaces, above code could be reduced as below:

@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);         }     }  } 

See also:

  • Our Servlet Filters wiki page
  • How to handle authentication/authorization with users in a database?
  • Using JSF 2.0 / Facelets, is there a way to attach a global listener to all AJAX calls?
  • Avoid back button on JSF web application
  • JSF: How control access and rights in JSF?
like image 122
BalusC Avatar answered Sep 16 '22 15:09

BalusC