Spring Security 4 XML Config JDBC Authentication Annotation Security Method

September 04, 2015 | Updated last October, 2015 | 2817 views | Comments

Store encrypted passwords to a MySQL database and use JDBC User Service of Spring Security 4 configured with XML using the Annotation Security Method to authenticate and authorize a certain user under Spring Web-MVC Framework 4.

 

Built and tested with the following:

  • Eclipse Juno IDE
  • Apache Tomcat 7.0.47
  • JDK 1.7.0
  • Maven 3.0.4
  • Spring Web-MVC Framework 4.2.2
    • Configuration: XML
    • Url Mapping: Annotation
  • Spring Security 4.0.2
    • Configuration: XML
    • Authentication: JDBC
    • Security Method: Annotation
  • MySQL 5.5.35
  • BCrypt Password Encoder

 

Task: Develop a system with user authentication and authorization wherein a "Seller" and a "Buyer" can log in. A "Buyer" should have a private page, inaccessible by the not logged in users. A "Seller" on the other hand, should have access to the "Buyer" page, aside from having access to the "Seller" private page. A user status can either be "Active" or "Inactive". "Inactive" users cannot log in on the system and the account is considered "Disabled".

 

Step 1. Set up MySQL TABLES and records.

Step 1.1 Create the "users" TABLE.

CREATE TABLE users (
  id BIGINT(50) NOT NULL AUTO_INCREMENT,
  username VARCHAR(25) NOT NULL,
  password VARCHAR(60) NOT NULL,
  isActive ENUM('0','1') NOT NULL DEFAULT '0',
  PRIMARY KEY (id)
);

This TABLE will hold user details such as the username, encrypted password, and user status defined as isActive.

 

Step 1.2 Insert three (3) users (buyer, seller, and disabled).

INSERT INTO users (username,password,isActive) VALUES ('buyer','$2a$10$CFWfv3DtqE1QNuVTxkbZ6eAkttkTM072JaSw3Pu6ZM0CsH0qBThu6','1'),('seller','$2a$10$O6e2f/71pJVtrdmtVmYjFOva90PUfSvrzJ7A1J4afUiJJBu5FzWc2','1'),('disabled','$2a$10$swq9Bx4GMqs7Uao4DIUGlejjNtLAQtG0IL4r8MRg3wBSz.etHOwm.','0');

Note: BCrypt will be used for password hashing.

  • buyer - password is buyer, an active user.
  • seller - password is seller, an active user.
  • disabled - password is disabled, an in-active user.

 

Step 1.3 Create the "roles" TABLE.

CREATE TABLE roles (
  id BIGINT(50) NOT NULL AUTO_INCREMENT,
  role VARCHAR(45) NOT NULL,
  PRIMARY KEY (id)
);

This is where all the available roles will be kept.

 

Step 1.4 Insert the "roles".

INSERT INTO roles (role) VALUES ('ROLE_BUYER'),('ROLE_SELLER');

  • One role for the "Buyer Page" access - "ROLE_BUYER".
  • One role for the "Seller Page" access - "SELLER PAGE".

 

Step 1.5 Create the "user_roles " TABLE.

CREATE TABLE user_roles (
  id BIGINT(50) NOT NULL AUTO_INCREMENT,
  user_id BIGINT(50) NOT NULL,
  role_id BIGINT(50) NOT NULL,
  PRIMARY KEY (id)
);

This is where the roles of each user will be stored.

 

Step 1.6 Insert roles of each user.

INSERT INTO user_roles (user_id,role_id) VALUES ('1','1'),('2','1'),('2','2'),('3','1');

  • buyer - Will have access to the Buyer Page.
  • seller - Will have access to the Buyer Page and Seller Page.
  • disabled - Will have access to the Buyer Page.

 

Step 2. Create a new Maven Project.

Enter the following details:

  • Group Id: com.consistentcoder
  • Artifact Id: spring-security-4-using-jdbc-user-service-with-xml-config-and-annotation-security-method
  • Name: spring security 4 using jdbc user service with xml config and annotation security method

Tutorials:
Create a New Maven Project in Eclipse
Configure Run on Server option on a Maven Project on Eclipse IDE

 

Your Maven Project Structure should look something like below.

 

Step 3. Edit pom.xml file.

Put the following code into it.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
 	<groupId>com.consistentcoder</groupId>
 	<artifactId>spring-security-4-using-jdbc-user-service-with-xml-config-and-annotation-security-method</artifactId>
 	<version>0.0.1-SNAPSHOT</version>
 	<packaging>war</packaging>
 	<name>spring security 4 using jdbc user service with xml config and annotation security method</name>
  
 	<properties>
        <spring.version>4.2.2.RELEASE</spring.version>
        <springSecurity.version>4.0.2.RELEASE</springSecurity.version>
    </properties>
  
    <dependencies>
        <!-- Spring MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>${springSecurity.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${springSecurity.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${springSecurity.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${springSecurity.version}</version>
        </dependency>
        
        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
    </dependencies>
</project>

/pom.xml

 

Step 4. Edit web.xml file.

Put the code below in replace of it's current code.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>spring-security-4-using-jdbc-user-service-with-xml-config-and-annotation-security-method</display-name>
    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-security.xml
        </param-value>
    </context-param>
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>
</web-app>

/src/main/webapp/WEB-INF/web.xml

 

Step 5. Create spring-servlet.xml file.

Create a new XML file and name it "spring-servlet.xml" on the same directory folder where "web.xml" is located.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:sec="http://www.springframework.org/schema/security"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-4.0.xsd">

    <sec:global-method-security pre-post-annotations="enabled" />   
    <context:component-scan base-package="com.consistentcoder.controllers" />
    <mvc:annotation-driven />
    <mvc:resources mapping="/resources/**" location="/resources/" />
    
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/jsp/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
</beans>

/src/main/webapp/WEB-INF/spring-servlet.xml

 

Step 6. Create spring-security.xml file.

Still on the same folder, create another XML file and name it "spring-security.xml" , then put the following code inside it.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd">

    <http auto-config="true">
        <form-login />
        <logout invalidate-session="true" />
    </http>
    
    <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://127.0.0.1:3306/test" />
        <beans:property name="username" value="root" />
        <beans:property name="password" value="r00tr00t" />
    </beans:bean>
    
    <beans:bean id="bcrypt" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <password-encoder ref="bcrypt"/>
            <jdbc-user-service id="jdbcUserService" data-source-ref="dataSource"
                users-by-username-query="
                select username, password, isActive as enabled 
                from users where username=?" 
                authorities-by-username-query="
                select u.username, r.role from users u, roles r, user_roles ur 
                where u.id=ur.user_id and r.id=ur.role_id and u.username=?" 
            />
        </authentication-provider>
    </authentication-manager>
</beans:beans>

/src/main/webapp/WEB-INF/spring-security.xml

 

Step 7. Create the template files.

Step 7.1. Create the folder.

A new folder should be created inside "WEB-INF" folder, name it "jsp".

 

Step 7.2. Create the home page template file.

Create a new ".jsp" file with the name "index.jsp" inside the new folder "jsp", and put the following code on it.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome! - ConsistentCoder.com</title>
</head>
<body>
<h1>${ message }</h1>
<p>
    <a href="<%=request.getContextPath()%>/seller">Seller Page</a> | <a href="<%=request.getContextPath()%>/buyer">Buyer Page</a> | <a href="<%=request.getContextPath()%>/login">Login</a>
</p>
<p><u>Seller login details</u></p>
<p>
    <ul>
        <li>username: <strong>seller</strong></li>
        <li>password: <strong>seller</strong></li>
    </ul>
</p>
<p><u>Buyer login details</u></p>
<p>
    <ul>
        <li>username: <strong>buyer</strong></li>
        <li>password: <strong>buyer</strong></li>
    </ul>
</p>
<p><u>Disabled login details</u></p>
<p>
    <ul>
        <li>username: <strong>disabled</strong></li>
        <li>password: <strong>disabled</strong></li>
    </ul>
</p>
</body>
</html>

/src/main/webapp/WEB-INF/js/index.jsp

 

Step 7.3. Create the buyer page template file.

Inside folder "jsp", another folder should be created with name "buyer". Create a new ".jsp" file, name it "buyer.jsp", put the following code inside it.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Buyer Page - ConsistentCoder.com</title>
</head>
<body>
<h1>${ message }</h1>
<p>
    <form id="logout" action="<%=request.getContextPath()%>/logout" method="post" >
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
        <input type="submit" value="logout" />
    </form>
</p>
</body>
</html>

/src/main/webapp/WEB-INF/js/buyer/buyer.jsp

 

Step 7.4. Create the seller page template file.

A folder with name "seller" should be created inside the folder "jsp", the inside it, create a new ".jsp" file with name "seller.jsp". Input the following code inside it.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Seller Page - ConsistentCoder.com</title>
</head>
<body>
<h1>${ message }</h1>
<p>You can also check the <a href="<%=request.getContextPath()%>/buyer">Buyer Page</a></p>
<p>
    <form id="logout" action="<%=request.getContextPath()%>/logout" method="post" >
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
        <input type="submit" value="logout" />
    </form>
</p>
</body>
</html>

/src/main/webapp/WEB-INF/js/seller/seller.jsp

 

The jsp template file structure should resemble the image below.

 

Step 8. Create the Controller Class.

Create a new package, name it "com.consistentcoder.controllers" and inside it create a new class,name it "Main".

Tutorials:
Create a New Package on Eclipse IDE
Create a New JAVA Class on Eclipse IDE

package com.consistentcoder.controllers;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class Main {
	@RequestMapping(value = "/", method = RequestMethod.GET)
    public String indexPage(ModelMap model) {
		
        model.addAttribute("message", "Hello Guest, this is the Home Page...");
        return "index";
    }
    
    @PreAuthorize("hasRole('ROLE_SELLER')")
    @RequestMapping(value = "/seller", method = RequestMethod.GET)
    public String sellerPage(ModelMap model) {
        
        model.addAttribute("message", "Seller Page...");
        return "seller/seller";
    }
    
    @PreAuthorize("hasAnyRole('ROLE_BUYER','ROLE_SELLER')")
    @RequestMapping(value = "/buyer", method = RequestMethod.GET)
    public String buyerPage(ModelMap model) {
        
        model.addAttribute("message", "Buyer Page...");
        return "buyer/buyer";
    }
}

/src/main/java/com/consistentcoder/constrollers/Main.java

 

That's all!

Spring Security 4 Using JDBC User Service with XML Config and Annotation Security Method has been developed.

 

Final Project Structure

 

What's Next? Test the application.

Browse the following link after you had started your server. http://localhost:8080/spring-security-4-using-jdbc-user-service-with-xml-config-and-annotation-security-method. "Home Page" will be displayed.

 

When a guest click on the Seller Page, "Buyer Page", "Login" links, that guest will be redirected to the "Login Page".

 

Login with the "Seller" details and browse the "Seller Page".

 

Login with the "Seller" details and browse the "Buyer Page".

 

Login with the "Buyer" details and browse the "Seller Page".

 

Login with the "Buyer" details and browse the "Buyer Page".

 

Login with "incorrect" details.

 

"Logout".

 

Login with "disabled" details.