Last updated on March 9th, 2024
In this example, we will learn how to use a custom login with database authentication using spring security in the spring boot example.
In this example, we will enter credentials like username and password in a custom login form and submit. Then validate the entered credential in a database table.
Table of content
1. Keep Eclipse IDE ready(STS integrated)
2. Create a Spring Boot Starter Project
3. Maven Dependency
4. Define Database configuration in the application.properties file
5. Create entity class
6. Create a repository
7. Create a service
8. Create a view page
9. Create a Controller class
10. Create a Spring Security Config class
11. Insert data into the database
12. Run the Application
13. Conclusion
1. Keep Eclipse IDE ready(STS integrated)
Refer to this article How to Create Spring Project in IDE to create Spring Boot Project in Eclipse IDE.
2. Create a Spring Boot Starter Project
Add the following dependencies:
• Spring Web
• Spring Security
• Thymeleaf
• MySQL Driver
• Spring Data JPA
Project Structure of Login with Database Authentication Spring Security
3. Maven Dependency
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.7.11</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springjava</groupId>
<artifactId>Spring_Security_Login_With_Database_Authentication</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Spring_Security_Login_With_Database_Authentication</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>16</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</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-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- <scope>runtime</scope> -->
<version>5.1.32</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4. Define Database configuration in the application.properties file
#Mysql Database
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/poc_db?useSSL=false
spring.datasource.username=root
spring.datasource.password=mysql
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
5. Create entity class
Role.java
package com.springjava.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
public Role() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
User.java
package com.springjava.entity;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = false)
private String password;
@ManyToMany
@LazyCollection(LazyCollectionOption.FALSE)
private Set<Role> roles;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
6. Create a repository
UserRepository.java
package com.springjava.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import com.springjava.entity.User;
public interface UserRepository extends JpaRepository<User, Integer> {
User findByUsernameOrEmail(String username, String email);
}
7. Create a service
UserDetail.java
package com.springjava.service;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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;
import com.springjava.entity.User;
import com.springjava.repository.UserRepository;
@Service
public class UserDetail implements UserDetailsService {
@Autowired
UserRepository userRepo;
@Override
public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException{
User user = userRepo.findByUsernameOrEmail(username, username);
if(user==null){
throw new UsernameNotFoundException("User not exists by Username");
}
Set<GrantedAuthority> authorities = user.getRoles().stream()
.map((role) -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toSet());
return new org.springframework.security.core.userdetails.User(username,user.getPassword(),authorities);
}
}
8. Create a view page
Create a view page under src/main/resources/templates.
login.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand">Spring Security Login With Database Authentication</a>
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</nav>
<br />
<br />
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<div th:if="${param.error}">
<div class="alert alert-danger">Invalid Username or Password</div>
</div>
<div th:if="${param.logout}">
<div class="alert alert-success">You have been logged out.</div>
</div>
<div class="card">
<div class="card-header">
<h2 class="text-center">Login</h2>
</div>
<div class="card-body">
<form method="post" role="form" th:action="@{/login}"
class="form-horizontal">
<div class="form-group mb-3">
<label class="control-label"> Username</label> <input type="text"
id="username" name="username" class="form-control"
placeholder="Enter username" />
</div>
<div class="form-group mb-3">
<label class="control-label"> Password</label> <input
type="password" id="password" name="password"
class="form-control" placeholder="Enter password" />
</div>
<div class="form-group mb-3">
<button type="submit" class="btn btn-primary">Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
home.html
<html lang="en"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand">Spring Security Login With Database Authentication</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" th:href="@{/logout}">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<br /><br />
<body>
<div class="container">
<div class="row">
<h1> Welcome to Spring Security world!</h1>
</div>
</div>
</body>
</html>
9. Create a Controller class
HomeController.java
package com.springjava.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String greeting() {
return "index";
}
@GetMapping("/login")
public String login() {
return "login";
}
@GetMapping("/admin")
public String admin() {
return "admin";
}
@GetMapping("/manager")
public String manager() {
return "manager";
}
@GetMapping("/employee")
public String employee() {
return "employee";
}
@GetMapping("/logout")
public String logout() {
return "redirect:/login";
}
}
10. Create a Spring Security Config class
SecurityConfig.java
package com.springjava.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
public class SecurityConfig {
@Bean
public static PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterSecurity(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
).formLogin(
form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/")
.permitAll()
).logout(
logout -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.permitAll()
);
return http.build();
}
}
11. Insert data into the database
INSERT INTO `user` VALUES
(1,'admin@gmail.com','admin','$2a$10$gqHrslMttQWSsDSVRTK1OehkkBiXsJ/a4z2OURU./dizwOQu5Lovu','admin'),
(2,'test@gmail.com','test'$2a$12$TYSPPDsgR1T9vpgMSavOteZoqzjGVLt7rzsqKLrGL4oQdE3rWDNru','test');
INSERT INTO `role` VALUES (1,'ROLE_ADMIN'),(2,'ROLE_USER');
INSERT INTO `user_role` VALUES (1,1),(2,2);
12. Run the Application
To run this application right-click on the application click on Run As then select the Run on Server option. After successfully running this application on the browser custom login form is shown.
Now enter the username as admin and password as admin or username as test and password as a test.
After login with a valid username and password
To logout click on the Logout
13. Conclusion
In this example, we learnt how to implement spring security database authentication in the spring boot example.