Spring Security 3.1 and JSF 2.0 Custom Form

Posted on Updated on

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.

20 thoughts on “Spring Security 3.1 and JSF 2.0 Custom Form

    Szymon said:
    August 3, 2012 at 8:14 PM

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

      Prabhat Jha responded:
      August 3, 2012 at 8:24 PM

      Can you check if your authentication manager dependency is injected ?

      MdRo said:
      October 29, 2012 at 6:17 AM

      You may need to use @Resource instead of @ManagedProperty

        Prabhat Jha responded:
        October 29, 2012 at 11:06 AM

        Even @ManagedProperty works well

      raouf ben hassine said:
      May 30, 2013 at 2:10 AM

      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

      sergio said:
      February 24, 2014 at 5:52 AM

      I had the same problem because I forget the alias=”authenticationManager” on the jsfspring-sec-security-config.xml

    MdRo said:
    October 29, 2012 at 5:16 PM

    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.

      Prabhat Jha responded:
      October 30, 2012 at 1:38 AM

      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.

    Andres said:
    November 20, 2012 at 2:32 AM

    They provide the source code, to see all the complete configurations. I am studying the security spring.

    pat said:
    December 20, 2012 at 8:03 AM

    Can you provide source code of this project pls?

    http://google.com said:
    February 13, 2013 at 3:40 AM

    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

    Andrii said:
    May 11, 2013 at 12:21 AM

    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

    assshooter said:
    May 11, 2013 at 7:23 AM

    very good thx 😀

      Alfredo Huerta Pinto said:
      August 3, 2013 at 7:05 AM

      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

    Alfredo Huerta Pinto said:
    August 3, 2013 at 7:05 AM

    index.jsp

    Alfredo Huerta Pinto said:
    August 3, 2013 at 7:06 AM

    response.sendRedirect(“pages/common/login.jsf”);

    not water said:
    August 9, 2013 at 8:16 PM

    thank you . this works great.

    wiggin said:
    November 29, 2013 at 3:51 PM

    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.

      wiggin said:
      November 29, 2013 at 3:53 PM

      the tag lib that i use is sec:authorize like this:
      sec:authorize ifAllGranted=’ROLE_ADMIN’

      Prabhat Jha responded:
      January 16, 2014 at 1:21 AM

      You can save the granted authority at session for later use

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