0

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.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Viola
  • 113
  • 4
  • 13

2 Answers2

2

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);
Jman
  • 481
  • 1
  • 4
  • 16
  • Thanks I will try the second version.I hope you could answer a few questions: SecurityFilter is it a managed bean? how to I put my user in the session? and how do I declare "logout" a navigation rule?Thanks again. – Viola Feb 05 '12 at 11:33
  • Security Filter is not a managed bean , only a class which implements PhaseListener interface. You can put your user to session in login method . I will give examples on my answer – Jman Feb 05 '12 at 11:59
  • Thanks!!! I am trying the second solution, but I seem not to be able to find the right path. My listener is in a folder called security. The web module is called ExpUI and it is within an application called Experience. SO I am using this path ExpUI.src.java.security.SecurityFilter in my tag. Do you know what I am doing wrong? ExpUI.src.java.security.SecurityFilter – Viola Feb 05 '12 at 12:22
  • you should create package not folder . we suppose that you create a package named security under your web project's source packages , you should only write that to your phase listener tag ; security.SecurityFilter – Jman Feb 05 '12 at 12:29
  • Thanks!!!!! It works. Instead of putting the user in the session I am checking a managed bean. However, when it redirects the page doesn't display properly. Do you know why? also how can I allow just a few pages to be visible when not logged in? Thank you so much!!!!I have a close deadline. – Viola Feb 05 '12 at 12:58
  • Not at all :) I think it will be slow to control user on managed bean but when it redirects to page is there /faces path in url ? if no , add to redirect string like that "/faces/redirectPage.xhtml" . And if you just allow a few pages when not logged in, it is better to create static page list that will allowed to visiter and control it if visiter on one of there pages where the phase listener control before navigate to logout – Jman Feb 05 '12 at 13:11
  • Hi thanks again. Everything works, the logedout rule wasn't working, even though I hade used faces in the path, I have changed the navigation to directly the Home page and now it displays properly. And I used the home page logic for the aother pages which are visible to non logged in user. Thanks again!!!! – Viola Feb 05 '12 at 14:47
0

There are many ways to achieve that. The easiest and probably the most popular way would be to use servlet filter, you can find more information about such a mechanism here: Basic Security in JSF

Community
  • 1
  • 1
Kris
  • 5,714
  • 2
  • 27
  • 47