Search Tutorials


Spring Boot 3 + MySQL + Security Basic Authentication Hello World Example

Spring Boot 3 + MySQL + Security Basic Authentication HelloWorld Example

In previous tutorial we implemented Spring Boot 3 + Security authentication simple example. In this tutorial we went through the the internal working of Spring Security. Also in another previous tutorial we had implemented Spring Boot 3 + MySQL + CRUD example. We will be modifying this example to implement basic authentication.

Basic authentication

Basic authentication in Spring Security is a very simple way to authenticate users based on their username and password. When a user tries to access a protected resource, they are prompted to enter their username and password. This information is then sent to the server in an encoded format. The server then compares this information to a list of valid username and password combinations to determine if the user is authorized to access the resource. If the username and password match, the user is granted access. If not, they are denied access. This is a basic and commonly used method of authentication in web applications.

Spring Boot 3 security basic authentication

Video

This tutorial is explained in the below Youtube Video.

Implementation

We will be modifying the code we had implemented previously for previous tutorial we had implemented Spring Boot 3 + MySQL + CRUD example.
We will first be modifying the pom.xml to add the spring security dependency.
<?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>3.2.2</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.javainuse</groupId>
	<artifactId>boot-mysql-crud</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>boot-mysql-crud</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
			<scope>runtime</scope>
		</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>
For basic authentication, when the user tries to perform CRUD operation the user will be asked for credentials i.e. username and password. Using this username and password spring security will create a User object for us. This User Object will then need to be compared with the User object we will be configuring in spring security. If they match then the authentication is successful.

Spring Boot 3 security basic authentication working

Bcrypt Encoding

Before we begin the code implementation let us first understand what is Bycrypt encoding and why is it used in by spring security. In a scenario where client credentials, such as usernames and passwords, are stored in a database, it is crucial to protect this information from unauthorized access. If the database is hacked or an employee gains unauthorized access to the database, they could potentially view the sensitive credentials, leading to a security breach. To address this issue, one solution is to utilize bcrypt encoding. Bcrypt encoding involves encrypting and storing passwords in the database in a secure manner. Bcrypt encryption is a one-way process, meaning that the encrypted password cannot be easily deciphered.
Let us have a look at Online Bcrypt Encoder to understand better.

Spring Boot 3 security bycrypt encoding
In spring esecurity when a user enters their password, it is compared with the stored bcrypt encoded password. If the two match, the system validates the user's identity and grants access, thereby ensuring secure authentication. By implementing bcrypt encoding, organizations can enhance the security of their stored credentials and mitigate the risk of unauthorized access.




Next we will be adding the following spring security configuration.
  • 1. The userDetailsService() method creates an in-memory user details service and creates a user with the username javainuse and password javainuse. The user is assigned the authority read.
  • 2. The passwordEncoder() method creates a BCryptPasswordEncoder bean to encode passwords.
  • 3. The filterChain() method configures the security filter chain for HTTP requests. It sets up HTTP basic authentication and authorizes any HTTP request to be authenticated.
So this code configures basic security settings with an in-memory user details service and basic authentication for all HTTP requests.
package com.javainuse.bootmysqlcrud;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

	@Bean
	UserDetailsService userDetailsService() {
		InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
		UserDetails user = User.withUsername("javainuse").password(passwordEncoder().encode("javainuse"))
				.authorities("read").build();
		userDetailsService.createUser(user);
		return userDetailsService;
	}

	@Bean
	BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http.httpBasic(Customizer.withDefaults());
		http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
		return http.build();
	}

}
Let us now look at the how this works for spring security.

No Credentials Provided


Spring Boot 3 security basic authentication No Credentials Provided

Spring Boot 3 security bycrypt encoding

Wrong Credentials


Spring Boot 3 security basic authentication Wrong Credentials

Spring Boot 3 security bycrypt encoding

Correct Credentials Provided


Spring Boot 3 security basic authentication Correct Credentials Provided

Spring Boot 3 security bycrypt encoding
Next we will be making changes to the the security configuration to create the spring security user using the MySQL database instead of using hard coded values.
Create the DAOUser. This code defines a class called DAOUser that represents a user entity in a database. The class is annotated with @Entity to indicate that it is a JPA entity and @Table(name = "user") specifies the name of the database table where the entity will be stored.
The class has three fields: id, username, and password. The id field is annotated with @Id and @GeneratedValue(strategy = GenerationType.IDENTITY) which specifies that it is the primary key for the entity and will be generated automatically by the database. The username and password fields are annotated with @Column which indicates that they are columns in the database table.
The class also has getter and setter methods for the username and password fields to allow access to and modification of these values. The password field is also annotated with @JsonIgnore, which means that it will be ignored during serialization and deserialization, providing an additional layer of security for sensitive data.
package com.javainuse.bootmysqlcrud.sec;

import com.fasterxml.jackson.annotation.JsonIgnore;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "user")
public class DAOUser {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;
	@Column
	private String username;
	@Column
	@JsonIgnore
	private String password;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
}
Create the repository interface for the User entity.
  • - It extends JpaRepository, which is a Spring Data interface for performing CRUD operations on the entity.
  • - The entity type for this repository is DAOUser and the primary key type is Integer.
  • - It also includes a custom query method findByUsername, which will return a DAOUser entity based on the given username.
package com.javainuse.bootmysqlcrud.sec;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<DAOUser, Integer> {
	DAOUser findByUsername(String name);
}
Next create the Spring service UserDetailsServiceImpl that implements the UserDetailsService interface. It is used for loading user details by username.
The code first injects the UserRepository dependency using the @Autowired annotation. Then, it overrides the loadUserByUsername method from the UserDetailsService interface. Inside this method, it retrieves a DAOUser object from the UserRepository using the username passed as a parameter. If the user is not found, it throws a UsernameNotFoundException.
If the user is found, it creates and returns a new User object from the Spring Security core with the username, password, and an empty list of granted authorities. This User object represents the authenticated user.

package com.javainuse.bootmysqlcrud.sec;

import java.util.ArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

	@Autowired
	private UserRepository userRepository;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		DAOUser daoUser = userRepository.findByUsername(username);
		if (daoUser == null) {
			throw new UsernameNotFoundException("User not found");
		}
		return new org.springframework.security.core.userdetails.User(daoUser.getUsername(), daoUser.getPassword(),
				new ArrayList<>());
	}

}
Next modify the SecurityConfig class
  • 2. The userDetailsService variable is autowired with an instance of UserDetailsServiceImpl, which is a custom implementation of the Spring UserDetailsService interface.
  • 3. The authenticationProvider method defines a bean of type AuthenticationProvider which is used for authenticating users. It creates a DaoAuthenticationProvider instance, sets the userDetailsService and passwordEncoder, and returns it.
package com.javainuse.bootmysqlcrud.sec;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

	@Autowired
	private UserDetailsServiceImpl userDetailsService;

	@Bean
	SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http.httpBasic(Customizer.withDefaults());
		http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
		return http.build();
	}

	@Bean
	public AuthenticationProvider authenticationProvider() {
		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
		authenticationProvider.setUserDetailsService(userDetailsService);
		authenticationProvider.setPasswordEncoder(passwordEncoder());
		return authenticationProvider;
	}

	@Bean
	BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

}
Finally go to MySQL database-
  • Use javainusedb
    

    Spring Boot 3 MySQL use database
  • Currently there are no records in Users table.
    Select * from User;
    

    Spring Boot 3 MySQL create Users table
  • Finally insert a record into the Users table. The password value should be a bcrypt.
    insert into user (username,password) values ("javainuse","bcrypt of javainuse");
    

    Spring Boot 3 MySQL insert into Users table

Download Source Code

Download it -
Spring Boot 3 Security Basic Authentication Example