Spring Security 3.1 and JSF 2.0 Custom Form

In the previous post we saw how to integrate Spring Security 3.1 and JSF 2.0.

To access the secure page Spring Security Provided us with a default login page.

In this post we will see how can we have a custom login page and use Spring Security for authentication.

First under pages folder create a new folder and name it common. Create a new xhtml under common folder and name it login.xhtml.

login.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>
	<div align="right" style="">
		<h:form	id="loginFormId" prependId="false">
				<div id="loginFieldsPnlId">
					<div id="loginFieldUsrContId">
						<h:outputText id="outTxtUserNameId" value="Username:" name="outTxtUserNameNm"></h:outputText>
						<h:inputText id="userName" required="true" value="#{loginMgmtBean.userName}" requiredMessage="Please enter username"></h:inputText>
						<h:outputLabel id="outLblUserNameId" for="userName" name="outLblUserNameNm"></h:outputLabel>
					</div>
					<div id="loginFieldPassContId">
						<h:outputText id="outTxtPasswordId" value="Password:" name="outTxtPasswordNm"></h:outputText>
						<h:inputSecret id="password"  required="true" value="#{loginMgmtBean.password}" requiredMessage="Please enter password" name="inTxtPasswordNm"></h:inputSecret>
						<h:outputLabel id="outLblPasswordId" for="password" name="outLblPasswordNm"></h:outputLabel>
					</div>
				</div>
				<div id="loginBtnPanelId">
					<h:commandButton id="btnLoginId" value="Login" action="#{loginMgmtBean.login}" styleClass="loginPanelBtn"></h:commandButton>
					<h:commandButton id="btnCancelId" value="Cancel" action="#{loginMgmtBean.cancel}" styleClass="loginPanelBtn" immediate="true" update="loginFormId"></h:commandButton>
				</div>
		</h:form>
	</div>
	<div>
		<h:messages></h:messages>
	</div>
</h:body>
</html>

Second lets write our LoginBean.

LoginBean


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 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 we have to configure our bean in spring bean definition, since we are not using annotation based injection.

jsfspring-sec-bean-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:sec="http://www.springframework.org/schema/security"
	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"
	   >
       
	<beans:bean id="navigator" name="navigator" class="com.mumz.jsfspringsec.beans.Navigator" scope="session">
	</beans:bean>
	
	<beans:bean id="loginBean" name="loginBean" class="com.mumz.jsfspringsec.beans.LoginBean" scope="prototype">
		<beans:property name="authenticationManager" ref="authenticationManager"></beans:property>
	</beans:bean>
	
</beans:beans>

Fourth we need to specify our login page to Spring Security, for this we need to change our jsfspring-sec-security-config.xml.

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="/**" access="permitAll"/>
		<sec:form-login login-page="/pages/common/login.jsf"/>
	</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>

Last portion is that we have to modify our faces-config.xml since we are not depending on implicit navigation.

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>
    	</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>

If you have followed every step as detailed in the earlier post and this one your project structure should look like below:


That’s it, deploy and run, we have successfully integrated Spring Security with custom login page using JSF 2.0.

There are 20 comments

  1. Szymon

    I have some problem – at the Authentication result = authenticationManager.authenticate(request) causes the NullPointer assignment error
    what is wrong?

    1. raouf ben hassine

      Hi there

      I have you solved your problem. I am facing the exact same one.
      I am novice in this field. Any help will be appreciated

  2. MdRo

    I’m wonder how to use spring security redirection (defined in security-config.xml, form-login) after login, logout, session expire etc. – here you use navigation-rules which is not a perfect way e.g. someone bookmarked page which is restricted and in your case it will always go to the same start page after logging in.

    1. Prabhat Jha

      You can try using a concept called as fully authenticated where in you decide if user is authenticated and then do authentication first and then let user navigate to the original URL , I will post a sample too.

  3. http://google.com

    Seems like u truly fully understand a lot related to this particular subject matter and that demonstrates thru this excellent article, termed “Spring Security 3.
    1 and JSF 2.0 Custom Form Java Holic”.
    Thanks a lot ,Chantal

  4. Andrii

    Nice topic, but I have a problem! The program is constantly
    displays the message “Bad credentials”. I added a logging into
    setUserName() method of LoginBean. As I see it, the problem is that
    the bean is created twice. And in the latter case, the userName
    sets as NULL. DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml
    reached end of additional filter chain; proceeding with original
    chain DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    org.springframework.security.web.access.ExceptionTranslationFilter
    – Chain processed normally DEBUG:
    org.springframework.security.web.context.HttpSessionSecurityContextRepository
    – SecurityContext is empty or contents are anonymous – context will
    not be stored in HttpSession. DEBUG:
    org.springframework.security.web.context.SecurityContextPersistenceFilter
    – SecurityContextHolder now cleared, as request processing
    completed DEBUG: org.springframework.security.web.FilterChainProxy
    – /login.xhtml at position 1 of 10 in additional filter chain;
    firing Filter: ‘SecurityContextPersistenceFilter’ DEBUG:
    org.springframework.security.web.context.HttpSessionSecurityContextRepository
    – HttpSession returned null object for SPRING_SECURITY_CONTEXT
    DEBUG:
    org.springframework.security.web.context.HttpSessionSecurityContextRepository
    – No SecurityContext was available from the HttpSession:
    org.apache.catalina.session.StandardSessionFacade@1a81ed21. A new
    one will be created. DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 2 of 10 in additional filter chain; firing Filter:
    ‘LogoutFilter’ DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 3 of 10 in additional filter chain; firing Filter:
    ‘UsernamePasswordAuthenticationFilter’ DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 4 of 10 in additional filter chain; firing Filter:
    ‘BasicAuthenticationFilter’ DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 5 of 10 in additional filter chain; firing Filter:
    ‘RequestCacheAwareFilter’ DEBUG:
    org.springframework.security.web.savedrequest.DefaultSavedRequest –
    pathInfo: both null (property equals) DEBUG:
    org.springframework.security.web.savedrequest.DefaultSavedRequest –
    queryString: both null (property equals) DEBUG:
    org.springframework.security.web.savedrequest.DefaultSavedRequest –
    requestURI: arg1=/; arg2=/login.xhtml (property not equals) DEBUG:
    org.springframework.security.web.savedrequest.HttpSessionRequestCache
    – saved request doesn’t match DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 6 of 10 in additional filter chain; firing Filter:
    ‘SecurityContextHolderAwareRequestFilter’ DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 7 of 10 in additional filter chain; firing Filter:
    ‘AnonymousAuthenticationFilter’ DEBUG:
    org.springframework.security.web.authentication.AnonymousAuthenticationFilter
    – Populated SecurityContextHolder with anonymous token:
    ‘org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc:
    Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated:
    true; Details:
    org.springframework.security.web.authentication.WebAuthenticationDetails@b364:
    RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId:
    52197670D90C7A1A2097082E4C48EAB8; Granted Authorities:
    ROLE_ANONYMOUS’ DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 8 of 10 in additional filter chain; firing Filter:
    ‘SessionManagementFilter’ DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 9 of 10 in additional filter chain; firing Filter:
    ‘ExceptionTranslationFilter’ DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml at
    position 10 of 10 in additional filter chain; firing Filter:
    ‘FilterSecurityInterceptor’ DEBUG:
    org.springframework.security.web.util.AntPathRequestMatcher –
    Checking match of request : ‘/login.xhtml’; against ‘/pages/**’
    DEBUG:
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor
    – Secure object: FilterInvocation: URL: /login.xhtml; Attributes:
    [permitAll] DEBUG:
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor
    – Previously Authenticated:
    org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc:
    Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated:
    true; Details:
    org.springframework.security.web.authentication.WebAuthenticationDetails@b364:
    RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId:
    52197670D90C7A1A2097082E4C48EAB8; Granted Authorities:
    ROLE_ANONYMOUS DEBUG:
    org.springframework.security.access.vote.AffirmativeBased – Voter:
    org.springframework.security.web.access.expression.WebExpressionVoter@6a8c1b5a,
    returned: 1 DEBUG:
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor
    – Authorization successful DEBUG:
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor
    – RunAsManager did not change Authentication object DEBUG:
    org.springframework.security.web.FilterChainProxy – /login.xhtml
    reached end of additional filter chain; proceeding with original
    chain DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    com.exadel.library.beans.Login – SET LOGIN: admin DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Creating instance of bean ‘login’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Returning cached instance of singleton bean
    ‘org.springframework.security.authenticationManager’ DEBUG:
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    – Finished creating instance of bean ‘login’ DEBUG:
    com.exadel.library.beans.Login – LOGIN: null DEBUG:
    org.springframework.security.authentication.ProviderManager –
    Authentication attempt using
    org.springframework.security.authentication.dao.DaoAuthenticationProvider
    DEBUG:
    org.springframework.security.authentication.dao.DaoAuthenticationProvider
    – User ‘NONE_PROVIDED’ not found трав 10, 2013 7:11:34 PM
    com.sun.faces.lifecycle.InvokeApplicationPhase execute WARNING:
    #{login.login}:
    org.springframework.security.authentication.BadCredentialsException:
    Bad credentials

    1. Alfredo Huerta Pinto

      good afternoon friends, I could help with this error: An
      Error Occurred: userName – Stack Trace
      java.lang.IllegalArgumentException: userName at
      javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:551)
      … Index.jsp Thanks

  5. wiggin

    i have a issue, this code works for me but, when i use the
    jsf taglib , i realize that the user role it’s not stored into the
    session because the parts of the view that are hidden or shown
    depending of user privileges, only works at request scope. For
    example when the web page is retrieve/refreshed again or the user
    navigate to other page the buttons that are shown only to admin
    role, didn’t show even if the user has been logged as
    administrator, is like the user was navigating as
    anonymous.

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 )

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s