http-redirectjsfweb.xmljava-ee-6

How to redirect a logged out user to the home page in Java EE/JSF?


I need to allow only logged-in users to most of the pages of my application. I am developing a Java Enterprise application with JSF 2. Does anyone know how I can do that? maybe with a config file?

I have a login component in the home page and I would like the users to be redirected to the home page when they click any other items of the page except a few.


Solution

  • There are different ways to do that . Firstly you can use filters to control page access or you can use phase listeners that listens jsf phases .

    I wanna give you two examples for them ;

      public class SecurityFilter implements Filter{
          FilterConfig fc;
    
       public void init(FilterConfig filterConfig)throws ServletException {
          fc = filterConfig;
       }
       public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
       throws IOException, ServletException{
          HttpServletRequest req = (HttpServletRequest)request;
          HttpServletResponse resp = (HttpServletResponse) response;
          HttpSession session = req.getSession(true);
    
          String pageRequested = req.getRequestURI().toString();
          if(session.getAttribute("user") == null && !pageRequested.contains("login.xhtml")){
             resp.sendRedirect("login.xhtml");
          }else{
            chain.doFilter(request, response);
          }
       }
       public void destroy(){
    
       }
    
    }
    

    And you should add this filter to web.xml;

    <filter>
        <filter-name>SecurityFilter</filter-name>
        <filter-class>com.webapp.SecurityFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>SecurityFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    

    Phase Listener example ;

    public class SecurityFilter implements PhaseListener {
    
    
        public void beforePhase(PhaseEvent event) {
        }
    
        public void afterPhase(PhaseEvent event) {
          FacesContext fc = event.getFacesContext();
    
          boolean loginPage =
          fc.getViewRoot().getViewId().lastIndexOf("login") > -1 ? true : false;
            if (!loginPage && !isUserLogged()) {
                 navigate(event,"logout");
            }
        }
    
        private boolean isUserLogged() {
            //looks session for user 
        }
        private void navigate(PhaseEvent event, String page) {
           FacesContext fc = event.getFacesContext();
           NavigationHandler nh = fc.getApplication().getNavigationHandler();
           nh.handleNavigation(fc, null, page);
        }
        public PhaseId getPhaseId() {
            return PhaseId.RESTORE_VIEW;
        }
    
    }
    

    So if you want to use listener you should add this to your faces-config.xml ; Note : "logout" is a navigation rule which is defined in faces-config

    <lifecycle>
     <phase-listener>com.myapp.SecurityFilter</phase>
    </lifecycle>
    

    Edit : The navigation rule ;

    <navigation-rule>
            <from-view-id>/*</from-view-id>
            <navigation-case>
                <from-outcome>logout</from-outcome>
                <to-view-id>/login.xhtml</to-view-id>
                <redirect/>
            </navigation-case>
        </navigation-rule>
    

    You can put your user to session in login method like that ;

    FacesContext context = FacesContext.getCurrentInstance(); 
    HttpSession session = 
    (HttpSession)context.getExternalContext().getSession(true); 
    
    session.setAttribute("user", loggedUser);