Adding Spring Security Logout Functionality to JSF 2.0

Posted on

In previous two posts: Integrating Spring Security 3.1 and JSF 2.0 and Spring Security 3.1 and JSF 2.0 Custom Form”, we integrated Spring Security 3.1 and JSF 2.0.
In this tutorial we will extend the functionality and we will add a logout functionality to our application.
First we will change our secured.xhtml and add a logout to it.

secured.xhtml

<!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:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
</h:head>
<h:body>
	<h:form>
		<h:outputLabel value="I am secured, if you are seeing me it means you have logged in correctly, great!"></h:outputLabel>
		<h:commandLink id="logout" action="#{loginMgmtBean.logout}" value="Logout"></h:commandLink>
		<h:messages></h:messages>
	</h:form>
</h:body>
</html>

Second we will update our LoginBean to add the logout action method.

LoginBean.java

package com.mumz.jsfspringsec.beans;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;

/**
 * The Class LoginBean.
 */
@ManagedBean(name="loginMgmtBean")
@RequestScoped
public class LoginBean {
	
	/** The user name. */
	private String userName = null;
	
	/** The password. */
	private String password = null;

	@ManagedProperty(value="#{authenticationManager}")
	private AuthenticationManager authenticationManager = null;
	/**
	 * Login.
	 * 
	 * @return the string
	 */
	public String login() {
		try {
			Authentication request = new UsernamePasswordAuthenticationToken(this.getUserName(), this.getPassword());
			Authentication result = authenticationManager.authenticate(request);
			SecurityContextHolder.getContext().setAuthentication(result);
		} catch (AuthenticationException e) {
			e.printStackTrace();
		}
		return "Secured";
	}
	
	/**
	 * Cancel.
	 * 
	 * @return the string
	 */
	public String cancel() {
		return null;
	}
	
	public String logout(){
		SecurityContextHolder.clearContext();
		return "loggedout";
	}

	public AuthenticationManager getAuthenticationManager() {
		return authenticationManager;
	}

	public void setAuthenticationManager(AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}

	/**
	 * Gets the user name.
	 *
	 * @return the user name
	 */
	public String getUserName() {
		return userName;
	}

	/**
	 * Sets the user name.
	 * 
	 * @param userName
	 *            the new user name
	 */
	public void setUserName(String userName) {
		this.userName = userName;
	}

	/**
	 * Gets the password.
	 * 
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * Sets the password.
	 * 
	 * @param password
	 *            the new password
	 */
	public void setPassword(String password) {
		this.password = password;
	}
}

Third since we are using JSF 2.0 explicit navigation we will update our faces-config.xml, to add the navigation for logout.

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">
    <!-- Enable Spring -->
    <application>
    	<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
    </application>
    <!-- Simple Navigation Rule -->
    <!-- If  user keys in ToSecure, move to /pages/secure/secured.xhtml-->
    <!-- Else If user keys in ToUnSecure, move to /pages/unsecure/unsecured.xhtml-->
    <navigation-rule>
    	<display-name>pages/home/home.xhtml</display-name>
    	<from-view-id>/pages/home/home.xhtml</from-view-id>
    	<navigation-case>
    		<from-action>#{navigator.navigateTo}</from-action>
    		<from-outcome>Secured</from-outcome>
    		<to-view-id>/pages/secure/secured.xhtml</to-view-id>
    		<redirect></redirect>
    	</navigation-case>
    </navigation-rule>
    <navigation-rule>
    	<display-name>pages/home/home.xhtml</display-name>
    	<from-view-id>/pages/home/home.xhtml</from-view-id>
    	<navigation-case>
    		<from-action>#{navigator.navigateTo}</from-action>
    		<from-outcome>UnSecured</from-outcome>
    		<to-view-id>/pages/unsecure/unsecured.xhtml</to-view-id>
    		<redirect></redirect>
    	</navigation-case>
    </navigation-rule>
    <navigation-rule>
    	<display-name>pages/secure/secured.xhtml</display-name>
    	<from-view-id>/pages/secure/secured.xhtml</from-view-id>
    	<navigation-case>
    		<from-action>#{loginMgmtBean.logout}</from-action>
    		<from-outcome>loggedout</from-outcome>
    		<to-view-id>/pages/home/home.xhtml</to-view-id>
    		<redirect></redirect>
    	</navigation-case>
    </navigation-rule>
    <navigation-rule>
    	<display-name>pages/common/login.xhtml</display-name>
    	<from-view-id>/pages/common/login.xhtml</from-view-id>
    	<navigation-case>
    		<from-action>#{loginMgmtBean.login}</from-action>
    		<from-outcome>Secured</from-outcome>
    		<to-view-id>/pages/secure/secured.xhtml</to-view-id>
    	</navigation-case>
    </navigation-rule>
</faces-config>

Final step is to update our jsfspring-sec-security-config.xml to add the logout functionality.

jsfspring-sec-security-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans 
	xmlns:sec="http://www.springframework.org/schema/security"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:beans="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="
	   http://www.springframework.org/schema/beans
	   http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	   http://www.springframework.org/schema/security
	   http://www.springframework.org/schema/security/spring-security-3.1.xsd">
	   
	 <sec:http auto-config="true" use-expressions="true">
		<sec:intercept-url pattern="/pages/secure/**" access="hasRole('ROLE_USER')" />
		<sec:intercept-url pattern="/pages/unsecure/**" access="permitAll"/>
		<sec:intercept-url pattern="/pages/common/**" access="permitAll"/>
		<sec:intercept-url pattern="/**" access="permitAll"/>
		<sec:form-login login-page="/pages/common/login.jsf"/>
		
		<sec:logout 
			invalidate-session="true" 
			delete-cookies="true" 
			logout-success-url="/"></sec:logout>
	</sec:http>
	
	<sec:authentication-manager alias="authenticationManager">
		<sec:authentication-provider>
			<sec:user-service>
				<sec:user authorities="ROLE_USER" name="admin" password="admin" />
			</sec:user-service>
		</sec:authentication-provider>
	</sec:authentication-manager>
</beans:beans>

Now deploy and run!

2 thoughts on “Adding Spring Security Logout Functionality to JSF 2.0

    Manuel José García Rodríguez said:
    February 5, 2014 at 5:39 AM

    that’s great, but one question, what happens if I hit the browser button back after loggin out, I am able to see the last visited page’s info, it should be redirected to loggin again, how to fix that ? thanks in advance.

      Prabhat Jha responded:
      June 24, 2014 at 2:05 AM

      It must have been cached by the browser, we can disable caching

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s