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