Spring Boot + Spring Security with Database Authentication (MySQL) + Rest API + Example

  • In this tutorial, we will learn Spring Security implementation with MySQL database authentication along with Rest API.
  • The end user will enter his/her email id as Username along with Password for authentication.

Microservice: Application Overview

In this example, we are exposing a Rest API (/login) for the end user authentication. URL: http://localhost:8080/springbootdbauth/login. On successful login it will return a message “User: Successfully logged in!” to the end user.

Microservice: Application Overview

Technology Stack

Java 8
Spring Boot 2.4.4
MySQL Connector - mysql-connector-java (8.0.23)
MYSQL 8.0

Application Database Schema

For demo, we need to create a table in bootdb database with following records. The end user will enter his/her email id as Username along with Password.

CREATE DATABASE bootdb;
USE bootdb;

CREATE TABLE Users (
     id int,
     userName varchar(255),
     email varchar(255),
     userPassword varchar(255),
     role varchar(10),
     created timestamp
 );
 
 insert into users (id, userName, email, userPassword, role, created) values(1,'username1', 'abc@xyz.com', 'pwd1','ADMIN', CURRENT_TIMESTAMP);
 insert into users (id, userName, email, userPassword, role, created) values(1,'username2', 'qrs@xyz.com', 'pwd2','USER', CURRENT_TIMESTAMP); 
MySQL Workbench
MySQL Workbench

Microservice: Application Structure

Overall application structure would be looked like as below.

Application Structure

Microservice: Maven File (pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.4</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>spring-boot-security-db-auth</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-security-db-auth</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Microservice: Application Configurations (application.properties)

# Applicationn context name
server.servlet.contextPath=/springbootdbauth

# Here 'bootdb' is the database name
spring.datasource.jdbcUrl=jdbc:mysql://localhost/bootdb?useSSL=false
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Microservice: Main Class – @SpringBootApplication

package com.the.basic.tech.info.securitydb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootMainApp {
	public static void main(String[] args) {
		SpringApplication.run(SpringBootMainApp.class, args);
	}
}

Microservice: @RestController (SpringController.java)

package com.the.basic.tech.info.securitydb.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SpringController {
	@RequestMapping("/login")
	public String userValidation() {
		return "User: Successfully logged in!";
	}
}

Microservice: Spring Security Configuration

This is the core part of this application. Here, we need to take care some basic points, like passwordEncoder – if you are using Spring Boot 2.x parent pom, then you have to use either passwordEncoder or {noop} operation during Spring Serurity implementaion other wise it will through exception.

package com.the.basic.tech.info.securitydb.configs;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

@SuppressWarnings("deprecation")
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

	private static final String usersQuery = "select email, userPassword, 1 FROM USERS where email = ?";
	private static final String rolesQuery = "select email, role FROM USERS where email = ?";

	@Autowired
	private DataSource ds;

	@Bean
	public static NoOpPasswordEncoder passwordEncoder() {
		return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
	}

	@Bean
	@ConfigurationProperties("spring.datasource")
	public DataSource ds() {
		return DataSourceBuilder.create().build();
	}

	/* Spring Security Configurations Starts */

	@Autowired
	public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
		auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).dataSource(ds).authoritiesByUsernameQuery(rolesQuery).passwordEncoder(passwordEncoder());
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.httpBasic().and().authorizeRequests().anyRequest().authenticated();
		http.csrf().disable();
	}
	/* Spring Security Configurations End */
}

Microservice: Build, Run and Test

For build and run the application below mvn command needs to be executed from command prompt.

Microsoft Windows [Version 10.0.17763.1935]
(c) 2018 Microsoft Corporation. All rights reserved.

D:\development\spring-boot-security-db-auth>mvn spring-boot:run
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building spring-boot-security-db-auth 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.4.4:run (default-cli) > test-compile @ spring-boot-security-db-auth >>>
[INFO]
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ spring-boot-security-db-auth ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 1 resource
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ spring-boot-security-db-auth ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ spring-boot-security-db-auth ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] skip non existing resourceDirectory D:\development\spring-boot-security-db-auth\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ spring-boot-security-db-auth ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] <<< spring-boot-maven-plugin:2.4.4:run (default-cli) < test-compile @ spring-boot-security-db-auth <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:2.4.4:run (default-cli) @ spring-boot-security-db-auth ---
[INFO] Attaching agents: []

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.4)

2021-06-26 14:09:22.606  INFO 18724 --- [           main] c.t.b.t.i.securitydb.SpringBootMainApp   : Starting SpringBootMainApp using Java 1.8.0_212 on LOCALHOST with PID 18724 (D:\development\spring-boot-security-db-auth\target\classes started by 172025 in D:\development\spring-boot-security-db-auth)
2021-06-26 14:09:22.606  INFO 18724 --- [           main] c.t.b.t.i.securitydb.SpringBootMainApp   : No active profile set, falling back to default profiles: default
2021-06-26 14:09:24.943  INFO 18724 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-06-26 14:09:24.959  INFO 18724 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-06-26 14:09:24.959  INFO 18724 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.44]
2021-06-26 14:09:25.097  INFO 18724 --- [           main] o.a.c.c.C.[.[.[/springbootdbauth]        : Initializing Spring embedded WebApplicationContext
2021-06-26 14:09:25.097  INFO 18724 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2406 ms
2021-06-26 14:09:25.476  INFO 18724 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-06-26 14:09:25.815  INFO 18724 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@45d6ef73, org.springframework.security.web.context.SecurityContextPersistenceFilter@77cb9cd1, org.springframework.security.web.header.HeaderWriterFilter@66f659e6, org.springframework.security.web.authentication.logout.LogoutFilter@2a1debfa, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@3e1624c7, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@35636217, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@e04ccf8, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3f29e26, org.springframework.security.web.session.SessionManagementFilter@6a0ac48e, org.springframework.security.web.access.ExceptionTranslationFilter@21a66d45, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@408b87aa]
2021-06-26 14:09:25.915  INFO 18724 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path '/springbootdbauth'
2021-06-26 14:09:25.946  INFO 18724 --- [           main] c.t.b.t.i.securitydb.SpringBootMainApp   : Started SpringBootMainApp in 3.918 seconds (JVM running for 4.481)

For testing just hit the URL: http://localhost:8080/springbootdbauth/login

Login page

Enter Username: abc@xyz.com and Password: pwd1 and click on Sign in button.

Login page

Once the user click on Sign in button, the user will be authenticated with database records and below message will be returned to the end user.

Successfull log in

Download Source Code (Attached)

Thank You 🙂