How to use a JEE Filter to secure JSF 2 application resources

When you are writing a JSF 2 application you can use more that just beans in it. JSF2 application is a JEE application so all mechanism can be used. In our example we are going to use a javax.servlet.Filter which protects resources that are available under /secured path of the application. Below image show how does our example work.

JSF 2 Login Filter Example - views, beans and filter components. Request and user interaction flow.

JSF 2 Login Filter Example – views, beans and filter components. Request and user interaction flow.

User requests a secured resource – the welcome.xhtml page which can be found under the /secured/welcome.xhtml path of our example application. At the beggining, request control goes to the LoginFilter which checks if user is logged in. At this time user is not logged in so filter redirects to the login.xhtml page where user can enter his username and password. This data is then POSTed to the application where LoginBean authenticates user based on the credentials send and redirects the request to the /secured/welcome.xhtml page. Next the LoginFilter checks if user is authenticated and redirects the request to the resource requested.

Here is our project structure.

JSF 2 Login Filter Example - Eclipse project structure

JSF 2 Login Filter Example – Eclipse project structure

Here you have application codes explained.

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.itcuties.examples.webapps</groupId>
  <artifactId>jsf2-filter-login</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>jsf2-filter-login</name>
  <url>http://www.itcuties.com</url>
  <dependencies>
	<!-- JSF 2 API -->
	<dependency>
		<groupId>com.sun.faces</groupId>
		<artifactId>jsf-api</artifactId>
		<version>2.2.0-m07</version>
		<scope>provided</scope>
	</dependency>
	<!-- Servlet API -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
  </dependencies>
  <build>
    <finalName>jsf2-filter-login</finalName>
  </build>
</project>


Since we are using JSF Beans and JEE Filter we need to have jsf-api and servlet-api artifacts in our project dependencies.

welcome.xhtml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html">
 
    <h:head>
        <title>Secured welcome page</title>
    </h:head>
    <h:body>
    	<h:form>
    		<h3>Welcome #{loginBean.username}</h3>
    		<br/>
    		<h:outputText value="This is a secured welcome page!"/>
    		<br/>
    		<h:commandLink action="#{loginBean.doLogout}" value="Logout"/>
    	</h:form>
    </h:body>
</html>

This is our secured resource. We display currently logged user username and a logout link, which is mapped to the doLogout method of the LoginBean.

login.xhtml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"htth://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html">
 
    <h:head>
        <title>Login form</title>
    </h:head>
    <h:body>
    	<h3>Login here</h3>
    	<h:form id="login-form">
    	   <h:outputText value="username:"/>
    	   <h:inputText value="#{loginBean.username}" id="username"/>
    	   <br/>
    	   <h:outputText value="password:"/>
    	   <h:inputSecret value="#{loginBean.password}" id="password"/>
    	   <br/>
    	   <h:commandButton id="button" value="Login" action="#{loginBean.doLogin}"/>
    	   <br/>
    	   <h:commandLink action="#{navigationBean.redirectToInfo}" value="Info page"/>
    	   <br/>
    	   <h:messages />
    	   <br/>
    	</h:form>
    </h:body>
</html>

This is a simple login page. User can enter his username and password. There is also a h:messages tag present here used to display informations to the user. This form action is mapped to the doLogin method of the LoginBean.

info.xhtml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"htth://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html">
 
    <h:head>
        <title>Info page</title>
    </h:head>
    <h:body>
    	<h:form>
    		<h3>Welcome</h3>
    		<br/>
    		<h:outputText value="This is an info page. Everyone has access to it!"/>
    		<br/>
    		<h:commandLink action="#{navigationBean.redirectToWelcome}" value="Secured Welcome page"/>
    	</h:form>
    </h:body>
</html>

This is a sample page available to all the users – those authenticated and guest. This page contains a link to the secured welcome page. CommandLink action is mapped to the redirectToWelcome method of the NavigationBean.

NavigationBean.java


package com.itcuties.examples.webapps.filterlogin.beans;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

/**
 * Simple navigation bean
 * @author itcuties
 *
 */
@ManagedBean
@SessionScoped
public class NavigationBean implements Serializable {

	private static final long serialVersionUID = 1520318172495977648L;

	/**
	 * Redirect to login page.
	 * @return Login page name.
	 */
	public String redirectToLogin() {
		return "/login.xhtml?faces-redirect=true";
	}
	
	/**
	 * Go to login page.
	 * @return Login page name.
	 */
	public String toLogin() {
		return "/login.xhtml";
	}
	
	/**
	 * Redirect to info page.
	 * @return Info page name.
	 */
	public String redirectToInfo() {
		return "/info.xhtml?faces-redirect=true";
	}
	
	/**
	 * Go to info page.
	 * @return Info page name.
	 */
	public String toInfo() {
		return "/info.xhtml";
	}
	
	/**
	 * Redirect to welcome page.
	 * @return Welcome page name.
	 */
	public String redirectToWelcome() {
		return "/secured/welcome.xhtml?faces-redirect=true";
	}
	
	/**
	 * Go to welcome page.
	 * @return Welcome page name.
	 */
	public String toWelcome() {
		return "/secured/welcome.xhtml";
	}
	
}

Here is a bean which is responsible for navigation in the application. All the methods started with redirect* word are used to send JSF request redirects. faces-redirect parameter set to true is used for that.

LoginBean.java


package com.itcuties.examples.webapps.filterlogin.beans;

import java.io.Serializable;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;


/**
 * Simple login bean.
 * 
 * @author itcuties
 */
@ManagedBean
@SessionScoped
public class LoginBean implements Serializable {

	private static final long serialVersionUID = 7765876811740798583L;

	// Simple user database :)
	private static final String[] users = {"anna:qazwsx","kate:123456"};
	
	private String username;
	private String password;
	
	private boolean loggedIn;

	@ManagedProperty(value="#{navigationBean}")
	private NavigationBean navigationBean;
	
	/**
	 * Login operation.
	 * @return
	 */
	public String doLogin() {
		// Get every user from our sample database :)
		for (String user: users) {
			String dbUsername = user.split(":")[0];
			String dbPassword = user.split(":")[1];
			
			// Successful login
			if (dbUsername.equals(username) && dbPassword.equals(password)) {
				loggedIn = true;
				return navigationBean.redirectToWelcome();
			}
		}
		
		// Set login ERROR
		FacesMessage msg = new FacesMessage("Login error!", "ERROR MSG");
        msg.setSeverity(FacesMessage.SEVERITY_ERROR);
        FacesContext.getCurrentInstance().addMessage(null, msg);
		
		// To to login page
		return navigationBean.toLogin();
		
	}
	
	/**
	 * Logout operation.
	 * @return
	 */
	public String doLogout() {
		// Set the paremeter indicating that user is logged in to false
		loggedIn = false;
		
		// Set logout message
		FacesMessage msg = new FacesMessage("Logout success!", "INFO MSG");
		msg.setSeverity(FacesMessage.SEVERITY_INFO);
		FacesContext.getCurrentInstance().addMessage(null, msg);
		
		return navigationBean.toLogin();
	}

	// ------------------------------
	// Getters & Setters 
	
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean isLoggedIn() {
		return loggedIn;
	}

	public void setLoggedIn(boolean loggedIn) {
		this.loggedIn = loggedIn;
	}

	public void setNavigationBean(NavigationBean navigationBean) {
		this.navigationBean = navigationBean;
	}
	
}

This is the main bean of our example application. It implements login (doLogin method) and logout (doLogout method) operations. Values entered on the login.xhtml page are mapped to the username and password attributes of this class. Those values are then checked against a static table containing username and password pairs. When user is successfully logged in then a loggedIn attribute is set to true. When user logs out this attribute is set to false.

LoginFilter.java


package com.itcuties.examples.webapps.filterlogin.filters;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itcuties.examples.webapps.filterlogin.beans.LoginBean;

/**
 * Filter checks if LoginBean has loginIn property set to true.
 * If it is not set then request is being redirected to the login.xhml page.
 * 
 * @author itcuties
 *
 */
public class LoginFilter implements Filter {

	/**
	 * Checks if user is logged in. If not it redirects to the login.xhtml page.
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// Get the loginBean from session attribute
		LoginBean loginBean = (LoginBean)((HttpServletRequest)request).getSession().getAttribute("loginBean");
		
		// For the first application request there is no loginBean in the session so user needs to log in
		// For other requests loginBean is present but we need to check if user has logged in successfully
		if (loginBean == null || !loginBean.isLoggedIn()) {
			String contextPath = ((HttpServletRequest)request).getContextPath();
			((HttpServletResponse)response).sendRedirect(contextPath + "/login.xhtml");
		}
		
		chain.doFilter(request, response);
			
	}

	public void init(FilterConfig config) throws ServletException {
		// Nothing to do here!
	}

	public void destroy() {
		// Nothing to do here!
	}	
	
}

This is a filter which protects all the secured resources of the application. It checks if a LoginBean is present in the application session and if the loggedIn attribute value is set to true – this indicates that user has successfully logged in to the application. If user is not logged then filter redirects requests to the login.xhtml page.

web.xml


<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
	<display-name>Sample JSF 2 Filter login app</display-name>

	<!-- Login filter -->
	<filter>
		<filter-name>LoginFilter</filter-name>
		<filter-class>com.itcuties.examples.webapps.filterlogin.filters.LoginFilter</filter-class>
	</filter>
	<!-- Set the login filter to secure all the pages in the /secured/* path of the application  -->
	<filter-mapping>
		<filter-name>LoginFilter</filter-name>
		<url-pattern>/secured/*</url-pattern>
	</filter-mapping>

	<!-- By default go to secured welcome page -->
	<welcome-file-list>
		<welcome-file>secured/welcome.xhtml</welcome-file>
	</welcome-file-list>

	<!-- Staring JSF -->
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- JSF URL mapping -->
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.xhtml</url-pattern>
	</servlet-mapping>

</web-app>

This is our application descriptor. It contains standard JSF configuration and our LoginFilter configuration which secures all the resources under the /secured path.

Download this sample code here.

This code is available on our GitHub repository as well.

13 Responses to "How to use a JEE Filter to secure JSF 2 application resources"

  1. Javi says:

    Perfect!!! Works perfectly!! What about if I need to read the username and password attributes from another class?

    Ldap.getUsername() is not working…

    “Cannot make a static reference to the non-static method getUsername() from the type LoginBean”

    Thanks!!!

    Reply
    • charlie says:

      Hello Javi,
      It seems that your Ldap class doesn’t have a static getUsername method that’s way you can’t call it this way. Make your Ldap class a Bean (use @ManagedBean annotation) and then let the JSF to set the reference to that class by writing something like this:

      @ManagedProperty(value="#{ldapBean}")
      private LdapBean ldap;
      
      ...
      
      public void setLdap(LdapBean ldapBean) {ldap=ldapBean}
      

      or if you are using JSF and Spring you can use the @Autowire annotation. See this tutorial – http://www.itcuties.com/j2ee/jsf-2-spring-3-example-the-registration-app/.

      Cheers!
      Charlie

      Reply
  2. Almustafa says:

    Excellent!!

    Work fine!

    Only left the timeout session value and ready!

    Thanks for you page.

    Reply
  3. Kitar Khalil says:
    LoginFilter.java
    .
    .
    .
    public class LoginFilter implements Filter {
            // For the first application request there is no loginBean in the session so user needs to log in
            // For other requests loginBean is present but we need to check if user has logged in successfully
            if (loginBean == null || !loginBean.isLoggedIn()) {
                String contextPath = ((HttpServletRequest)request).getContextPath();
                ((HttpServletResponse)response).sendRedirect(contextPath + "/login.xhtml");
            }
            /* Adding else here */
            else chain.doFilter(request, response);     
        }
        . 
        .
        .
    }
    

    you have to put :

    else chain.doFilter(request, response);
    

    or it won’t work.

    Reply
  4. Jorge says:

    Nice and simple, excellent example. Cheers!

    Reply
  5. Ruben says:

    Awesome example!

    I’m getting an error when trying to navigate from info to welcome: Unable to set property navigationBean for managed bean loginBean
    What I basically need to know is how and when the property is set and how I can manipulate that.
    I’m trying to implement a similar sollution on another project.

    Thanks in advance

    Reply
    • itcuties says:

      Hello Rubin, the navigationBean property is set because of the annotation and the setter method in the LoginBean’s code

      @ManagedProperty(value="#{navigationBean}")
      private NavigationBean navigationBean;
      
      ...
      
      public void setNavigationBean(NavigationBean navigationBean) {
          this.navigationBean = navigationBean;
      }
      
      Reply
    • fritz says:

      It works, thx.

      But I had to change two things:
      1. In the web.xml I had to move the section to the end of the file (inside ). I’m not familiar with xml, so I just did what eclipse (Kepler) told me.

      2. I am running the webapps under tomcat7. So in pom.xml I had to change the scope for the jsf-api to compile and add the dependency for jsf-impl. With the changes Maven copies the libaries to WEB_INF/lib during the packaging.

      Reply
  6. n0life says:

    I really love you guys !!! I was so desperate I didn’t know there was a java method like interface filter to solve the problem of authentication and securty which we can use with web.xml , I really searched a lot and all that I found was about role and group and realm and all that shit of glassfish , I couldn’t understand it well :S

    Reply
    • itcuties says:

      We are happy you guys like our posts, please share it so that we can make more topics :) Have a nice day.

      Reply
  7. darevalor says:

    Hello,

    First, sorry for my english… :P

    How can i do to redirect to a login page when i press on logout link?. In this example when I do that it returns to welcome page and shows the Logout success message. Then if i press on logout link again it returns to login page… I check all the example with my project and all is ok. I dont know why this is happend…

    Thanks…

    Reply
  8. Koc says:

    Helo, I have a problem with the code. the filter just isnt working, I cant access the welcome page from the link without having to log in. Ive add the filter in xml and the code is the same as here. thx

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Java by Example App is available at Google Play Store NOW