Spring Security with JDBC User Details and JSF 2.0

Posted on Updated on

We will add on to our last remember me tutorial.

In this tutorial instead of hard coded username, password we will add JDBC default support provided by Spring.

First we will update jsfspring-sec-bean-config.xml and add datasource property. In this tutorial we will use MySQL.

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:property name="rememberMeServices" ref="rememberMeServices"></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="userDetailsService" /> 
		<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: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_sec_default" />
		<beans:property name="username" value="root" />
		<beans:property name="password" value="root" />
   </beans:bean>
</beans:beans>

Second we will update our jsfspring-sec-security-config.xml and add jdbc-user-service as authentication manager.

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: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 >
			<sec:jdbc-user-service data-source-ref="dataSource" id="userDetailsService"/>
		</sec:authentication-provider>
	</sec:authentication-manager>	
</beans:beans>

Since we are using default JDBC template provided by Spring, we don’t have to write any Java Code.
Third we will create our schema.

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';

DROP SCHEMA IF EXISTS `jsf_spring_sec_default` ;
CREATE SCHEMA IF NOT EXISTS `jsf_spring_sec_default` DEFAULT CHARACTER SET latin1 ;
USE `jsf_spring_sec_default` ;

-- -----------------------------------------------------
-- Table `jsf_spring_sec_default`.`users`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `jsf_spring_sec_default`.`users` ;

CREATE  TABLE IF NOT EXISTS `jsf_spring_sec_default`.`users` (
  `username` VARCHAR(50) NOT NULL ,
  `password` VARCHAR(50) NOT NULL ,
  `enabled` VARCHAR(50) NOT NULL ,
  PRIMARY KEY (`username`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;

-- -----------------------------------------------------
-- Table `jsf_spring_sec_default`.`authorities`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `jsf_spring_sec_default`.`authorities` ;

CREATE  TABLE IF NOT EXISTS `jsf_spring_sec_default`.`authorities` (
  `username` VARCHAR(50) NOT NULL ,
  `authority` VARCHAR(50) NOT NULL ,
  INDEX `fk_authorities_users` (`username` ASC) ,
  CONSTRAINT `fk_authorities_users`
    FOREIGN KEY (`username` )
    REFERENCES `jsf_spring_sec_default`.`users` (`username` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;

-- -----------------------------------------------------
-- Table `jsf_spring_sec_default`.`groups`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `jsf_spring_sec_default`.`groups` ;

CREATE  TABLE IF NOT EXISTS `jsf_spring_sec_default`.`groups` (
  `id` INT(11) NOT NULL AUTO_INCREMENT ,
  `group_name` VARCHAR(50) NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;

-- -----------------------------------------------------
-- Table `jsf_spring_sec_default`.`group_authorities`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `jsf_spring_sec_default`.`group_authorities` ;

CREATE  TABLE IF NOT EXISTS `jsf_spring_sec_default`.`group_authorities` (
  `group_id` INT(11) NOT NULL ,
  `authority` VARCHAR(50) NOT NULL ,
  PRIMARY KEY (`group_id`) ,
  INDEX `fk_group_authorities_group` (`group_id` ASC) ,
  CONSTRAINT `fk_group_authorities_group`
    FOREIGN KEY (`group_id` )
    REFERENCES `jsf_spring_sec_default`.`groups` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;

-- -----------------------------------------------------
-- Table `jsf_spring_sec_default`.`group_members`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `jsf_spring_sec_default`.`group_members` ;

CREATE  TABLE IF NOT EXISTS `jsf_spring_sec_default`.`group_members` (
  `id` INT(11) NOT NULL AUTO_INCREMENT ,
  `username` VARCHAR(50) NOT NULL ,
  `group_id` INT(11) NOT NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_group_members_group` (`id` ASC) ,
  CONSTRAINT `fk_group_members_group`
    FOREIGN KEY (`id` )
    REFERENCES `jsf_spring_sec_default`.`groups` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

Records required to run application.

INSERT INTO `users` VALUES ('admin','admin','1'),('guest','guest','1');

INSERT INTO `authorities` VALUES ('admin','ROLE_USER'),('guest','ROLE_USER'),('admin','ROLE_ADMIN');

Note : – We don’t need all the tables here, since we are not using “Group-Based Access Control” we just need two tables namely Users and Authority.

We are saving plain text password which is not advisable, later we will use Spring to use different encrypting mechanism.

3 thoughts on “Spring Security with JDBC User Details and JSF 2.0

    Jatin said:
    April 22, 2013 at 1:19 PM

    This particular functionality of yours is not working. Its accepting the correct usename and password but when wrong credentials are entered it still takes you to the successfully logges in page. Kindly check.

    Antonio Lazaro said:
    May 13, 2013 at 4:48 AM

    I Believe this happens because is missing this in
    sec:jdbc-user-service: users-by-username-query=” select
    username,password, enabled from users where username=? and enabled
    = 1″ authorities-by-username-query=” select u.username,
    au.authority from users u, authorities au where u.user_id =
    au.user_id and u.username =? ” Be like that: If it did’t work,
    review your connection debugging.

    Alexandru said:
    November 24, 2014 at 4:07 AM

    It works nicely with Spring 4.0.1 and MySQL 5.6.16 Thanks!

    Though I preferred to test the code above based on a previous article, without remember me functionality:
    http://mprabhat.com/2012/07/11/spring-security-3-1-and-jsf-2-0-custom-form/

    So in this case I needed to add only the following to the project, no change to the LoginBean class is required.

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