Spring Security 3.1 Authentication using Custom Database Implementation and JSF 2.0

In the last tutorial we used default database configuration required by Spring Security and we moved out of hard coded user credentials.

But there is every possibility that their is already a existing database for user management and we cannot create new tables as required by Spring Security default behavior.

This can be achieved very easily in few steps, let’s see it in action.

First we have to create a new class which will extend JdbcDaoImpl, currently we don’t have any other functionality to place inside our custom implementation, so we will just extend the default behavior provided by JdbcDaoImpl, but in real world you can have many other functionality as part of your implementation.

CustomJDBCDaoImpl.java
[sourcecode language=”java”]
package com.mumz.jsfspringsec.dao;

import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;

public class CustomJDBCDaoImpl extends JdbcDaoImpl {
public CustomJDBCDaoImpl(){
super();
}
}
[/sourcecode]

Second we need to update our jsfspring-sec-bean-config.xml and add the custom implementation.

jsfspring-sec-bean-config.xml
[sourcecode language=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot;
xmlns:beans="http://www.springframework.org/schema/beans&quot;
xmlns:sec="http://www.springframework.org/schema/security&quot;
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&quot;
>

<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:property name="rememberMeServices" ref="rememberMeServices"></beans:property>
<beans:property name="userDetailsService" ref="customjdbcUserService"></beans:property>
</beans:bean>

<beans:bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
<beans:property name="url" value="jdbc:mysql://localhost:3306/jsf-spring-security" />
<beans:property name="username" value="root" />
<beans:property name="password" value="root" />
</beans:bean>

<beans:bean id="customjdbcUserService" class="com.mumz.jsfspringsec.dao.CustomJDBCDaoImpl">
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="enableAuthorities" value="true"/>
<beans:property name="usersByUsernameQuery">
<beans:value>SELECT JSF_SPRING_SEC_USERS_USERNAME, JSF_SPRING_SEC_USERS_PASSWORD, JSF_SPRING_SEC_USERS_ENABLED FROM JSF_SPRING_SEC_USERS WHERE JSF_SPRING_SEC_USERS_USERNAME = ?</beans:value>
</beans:property>
<beans:property name="authoritiesByUsernameQuery">
<beans:value>
select JSF_SPRING_SEC_ROLES_USERNAME,JSF_SPRING_SEC_ROLES_ROLE_NAME from JSF_SPRING_SEC_ROLES where JSF_SPRING_SEC_ROLES_USERNAME = ?
</beans:value>
</beans:property>
</beans:bean>

<beans:bean id="rememberMeServices"
class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<beans:property name="key" value="jsfspring-sec" />
<beans:property name="userDetailsService" ref="customjdbcUserService" />
<beans:property name="alwaysRemember" value="true" />
<beans:property name="tokenValiditySeconds" value="60" />
</beans:bean>

<beans:bean id="rememberMeAuthenticationProvider"
class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<beans:property name="key" value="jsfspring-sec"/>
</beans:bean>

<beans:bean id="rememberMeFilter"
class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<beans:property name="rememberMeServices" ref="rememberMeServices"/>
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
</beans:beans>
[/sourcecode]

Important thing to note above:

  1. Since we are overriding the default behaviour we have to specify queries for loading username and authorities, which is what we have done for usersByUsernameQuery and authoritiesByUsernameQuery

Third step is to use this custom implementation with our authentication manager in jsfspring-sec-security-config.xml.

jsfspring-sec-security-config.xml
[sourcecode language=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot;
xmlns:sec="http://www.springframework.org/schema/security&quot;
xmlns:beans="http://www.springframework.org/schema/beans&quot;
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"&gt;

<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:remember-me key="jsfspring-sec" services-ref="rememberMeServices"/>
<sec:logout
invalidate-session="true"
delete-cookies="JSESSIONID,SPRING_SECURITY_REMEMBER_ME_COOKIE"
logout-success-url="/pages/common/login.jsf"></sec:logout>
</sec:http>

<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="rememberMeAuthenticationProvider"></sec:authentication-provider>
<sec:authentication-provider user-service-ref="customjdbcUserService">
</sec:authentication-provider>
</sec:authentication-manager>
</beans:beans>
[/sourcecode]

Database schema
[sourcecode language=”sql”]
delimiter $$

CREATE DATABASE `jsf-spring-security` /*!40100 DEFAULT CHARACTER SET utf8 */$$

CREATE TABLE `jsf_spring_sec_users` (
`PK_JSF_SPRING_SEC_USERS` int(11) NOT NULL AUTO_INCREMENT,
`JSF_SPRING_SEC_USERS_USERNAME` varchar(45) NOT NULL,
`JSF_SPRING_SEC_USERS_PASSWORD` varchar(255) NOT NULL,
`JSF_SPRING_SEC_USERS_ENABLED` varchar(5) NOT NULL,
`JSF_SPRING_SEC_USERS_CREATED_DT` varchar(45) NOT NULL,
`JSF_SPRING_SEC_USERS_MODIFIED_DT` varchar(45) DEFAULT NULL,
PRIMARY KEY (`PK_JSF_SPRING_SEC_USERS`),
UNIQUE KEY `JSF_SPRING_SEC_USERS_USERNAME_UNIQUE` (`JSF_SPRING_SEC_USERS_USERNAME`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

CREATE TABLE `jsf_spring_sec_roles` (
`PK_JSF_SPRING_SEC_ROLES` int(11) NOT NULL AUTO_INCREMENT,
`JSF_SPRING_SEC_ROLES_USERNAME` varchar(45) NOT NULL,
`JSF_SPRING_SEC_ROLES_ROLE_NAME` varchar(45) NOT NULL,
`JSF_SPRING_SEC_ROLES_CREATED_DT` varchar(45) NOT NULL,
`JSF_SPRING_SEC_ROLES_MODIFIED_DT` varchar(45) DEFAULT NULL,
PRIMARY KEY (`PK_JSF_SPRING_SEC_ROLES`),
KEY `FK_USERNAME_JSF_SPRING_SEC_ROLES` (`JSF_SPRING_SEC_ROLES_USERNAME`),
CONSTRAINT `FK_USERNAME_JSF_SPRING_SEC_ROLES` FOREIGN KEY (`JSF_SPRING_SEC_ROLES_USERNAME`) REFERENCES `jsf_spring_sec_users` (`JSF_SPRING_SEC_USERS_USERNAME`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

INSERT INTO `jsf_spring_sec_users` VALUES (1,’admin’,’admin’,’true’,’2012-07-17 10:07:41′,’2012-07-17 10:07:41′),(2,’guest’,’guest’,’true’,’2012-07-17 16:59:13′,’2012-07-17 16:59:13′);

INSERT INTO `jsf_spring_sec_roles` VALUES (1,’admin’,’ROLE_USER’,’2012-07-17 16:57:49′,’2012-07-17 16:57:49′),(2,’admin’,’ROLE_ADMIN’,’2012-07-17 16:58:08′,’2012-07-17 16:58:08′),(3,’guest’,’ROLE_USER’,’2012-07-17 16:59:17′,’2012-07-17 16:59:17′);

[/sourcecode]

Only three steps are required for mapping our custom implementation. Enjoy!


Posted

in

, , ,

by

Comments

3 responses to “Spring Security 3.1 Authentication using Custom Database Implementation and JSF 2.0”

  1. robbinwooo (@robbinwooo) Avatar

    Sir,thanks a lot for your tutorial.I followed this series one by one,but I got a NullPointerException from this tutorial while checking the remeberme check box,please advise.

    Warning: #{loginMgmtBean.login}: java.lang.NullPointerException
    javax.faces.FacesException: #{loginMgmtBean.login}: java.lang.NullPointerExcepti
    on
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionList
    enerImpl.java:118)

    1. chandu Avatar
      chandu

      Sir, thanks a lot for your tutorial. I have tried custom
      database example . but it shows
      org.springframework.security.authentication.BadCredentialsException:
      Bad credentials for all input please help me..

    2. kaotic Avatar
      kaotic

      me too i’m getting this error, have you resolved this problem, please let me know how to resolve it

Leave a Reply

Discover more from Code Holic

Subscribe now to keep reading and get access to the full archive.

Continue reading