In continuation to previous article on two different ways of implementing Spring Security, here in this article we will learn the third way โHow to implement Security in Spring Boot using UserDetailsService?โ. After going through the previous article, I hope we all are very familiar with basics of Security and even the basics of Security in a Spring Boot application. This time we will create a user registration form and save users with their roles into database. Then, based on the user role, we will check the authentication and authorization functionalities with the help of predefined UserDetailsService.
If you are looking for โHow to implement Security in Spring Boot using UserDetailsService with Spring Boot 3 onward?, kindly visit a separate article on Spring Security UserDetailsService Using Spring Boot 3.
To illustrate, we will take some roles into effect and play around them in the whole process to make it crystal clear. Additionally, we will have some pages and restrict them to be accessible by some specific roles only. Equally important, we will have to create a small MVC web application to make registration process open for users. Users will enter their roles while doing registration. Then we can implement security features on top of it. Letโs start working on our topic โHow to implement Security in Spring Boot using UserDetailsService?โ accordingly.
Table of Contents (Click on links below to navigate)
What can you expect from this article on the whole?
1) What is an UserDetailsService concept in the context of Spring Security?
2) What is the benefits of implementing UserDetailsService?
3) How to implement Security in Spring Boot using UserDetailsService?
4) How does UserDetailsService internally work in Spring Security application with flow diagram?
5) Moreover, how to use annotations :@EnableWebSecurity, @Configuration, @Bean, @GetMapping, @Autowired, @Data, @Entity, @Table, @Id, @GeneratedValue, @Column, @ElementCollection, @CollectionTable, @JoinColumn, @Service
6) How to develop a user registration app using Spring MVC with Thymeleaf?
7) How to test the Security enabled application?
8) How to implement Security in Spring Boot using UserDetailsService Without WebSecurityConfigurerAdapter?
What is UserDetailsService all about ? What is the benefit of using it?
UserDetailsService is a predefined interface exists under package org.springframework.security.core.userdetails in Spring. Our implementation class implements this interface and overrides itโs loadUserByUsername(String username) method. This method returns UserDetails which is again an interface. Predefined User class (org.springframework.security.core.userdetails.User) is an implementation of UserDetails interface. In summary, in loadUserByUsername(String username) method we pass our username and it returns us predefined User object(org.springframework.security.core.userdetails.User).
In fact, we provide only username to UserDetailsService and some small configurations and we get all role based security functionality implemented as part of the framework. Accordingly, we save a lot of effort in implementing security.
How to implement UserDetailsService Security in our application ?
First of all, you must have a Spring Boot web application where in you will have a form i.e. a kind of User registration form. As part of the Spring MVC structure you will have a UserService implementation class. Letโs say it UserServiceImpl.java. The second thing to remember is that you have to convert your User object into predefined Springโs User object. Further, please follow below steps to get UserDetailsService implemented in your application.
1) Your user service class โUserServiceImpl.javaโ should implement interface UserDetailsService.java(Provided by Spring)
2) Equally important, Override loadUserByUsername(String username) method of interface UserDetailsService in your UserServiceImpl class.
3) As part of implementation,
(A) Get your User Object with the help of username/email from UserRepository.
(B) Convert your User Object into Springโs predefined User object(org.springframework.security.core.userdetails.User) accordingly.
(C) Return Spring defined User object which is an implementation of UserDetails(methodโs return type).
Below code represents the implementation of UserDetailsService. However, you will see the complete code in below sections consequently.
UserServiceImpl.java
@Service
public class UserServiceImpl implements IUserService, UserDetailsService{
@Autowired
private UserRepository userRepo;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Optional<User> opt = userRepo.findUserByEmail(email);
org.springframework.security.core.userdetails.User springUser=null;
if(opt.isEmpty()) {
throw new UsernameNotFoundException("User with email: " +email +" not found");
}else {
User user =opt.get();
List<String> roles = user.getRoles();
Set<GrantedAuthority> ga = new HashSet<>();
for(String role:roles) {
ga.add(new SimpleGrantedAuthority(role));
}
springUser = new org.springframework.security.core.userdetails.User(
email,
user.getPassword(),
ga );
}
return springUser;
}
//Other Approach: Using Lambda & Stream API of Java 8
/*@Override
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
Optional<User> opt = userRepo.findUserByEmail(email);
if(opt.isEmpty())
throw new UsernameNotFoundException("User with email: " +email +" not found !");
else {
User user = opt.get();
return new org.springframework.security.core.userdetails.User(
user.getEmail(),
user.getPassword(),
user.getRoles()
.stream()
.map(role-> new SimpleGrantedAuthority(role))
.collect(Collectors.toSet())
);
}*/
}
How does UserDetailsService internally work in Spring Security application ?

As soon as the user enters username & password and click on the Login button, WebSecurityConfigurerAdapter is called which internally calls UserServiceImpl.java (Implementation class, provided by the programmer). Furthermore, loadUserByUserName( ) method implemented in UserServiceImpl.java converts our User Object into Spring provided User object. Also, our SecurityConfig.java extends WebSecurityConfigurerAdapter and provides an implementation of authentication & authorization logics in two methods; configure(AuthenticationManagerBuilder) & configure(HttpSecurity) respectively as shown in below code.
SecurityConfig.java
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService uds;
@Autowired
private BCryptPasswordEncoder encoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(uds).passwordEncoder(encoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/home","/register","/saveUser").permitAll()
.antMatchers("/welcome").authenticated()
.antMatchers("/admin").hasAuthority("Admin")
.antMatchers("/mgr").hasAuthority("Manager")
.antMatchers("/emp").hasAuthority("Employee")
.antMatchers("/hr").hasAuthority("HR")
.antMatchers("/common").hasAnyAuthority("Employeee,Manager,Admin")
.anyRequest().authenticated()
.and()
.formLogin()
.defaultSuccessUrl("/welcome",true)
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and()
.exceptionHandling()
.accessDeniedPage("/accessDenied");
}
}
Note: Spring Security 5.7.0-M2 onward, WebSecurityConfigurerAdapter has been deprecated. Hence, If you are using Spring Security 5.7.0-M2 or later versions, please update your implementation as shown in below code snippet. Moreover, in order to learn the new way of implementing custom configuration class, visit a separate article on Spring Security without WebSecurityConfigurerAdapter.
SecurityConfig.java
package com.dev.springboot.security.UserDetailsService.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Autowired
private UserDetailsService uds;
@Autowired
private BCryptPasswordEncoder encoder;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/home","/register","/saveUser").permitAll()
.antMatchers("/welcome").authenticated()
.antMatchers("/admin").hasAuthority("Admin")
.antMatchers("/mgr").hasAuthority("Manager")
.antMatchers("/emp").hasAuthority("Employee")
.antMatchers("/hr").hasAuthority("HR")
.antMatchers("/common").hasAnyAuthority("Employeee,Manager,Admin")
.anyRequest().authenticated()
.and()
.formLogin()
.defaultSuccessUrl("/welcome",true)
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and()
.exceptionHandling()
.accessDeniedPage("/accessDenied")
.and()
.authenticationProvider(authenticationProvider());
return http.build();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(uds);
authenticationProvider.setPasswordEncoder(encoder);
return authenticationProvider;
}
}
Example of implementing UserDetailsService
To illustrate the implementation of UserDetailsService, letโs assume an internal portal of a small company. In company we have various roles within employees such as Admin, HR, Manager and of course Employee as well. Additionally, the Portal has role based access to pages. Even Some pages are accessible to all roles while others are restricted to some particular roles.
Equally important, the company will have a user registration page which must be accessible to all users, even without login. Now letโs create a standard user registration flow as given below.

What Software/Technologies would you need?
โฆSTS (Spring Tool Suite) : Version-> 4.7.1.RELEASE
โDependent Starters : Spring Security, Thymeleaf, Spring Web, Lombok, Spring Data JPA, MySQL Driver, Spring Boot DevTools
โฆMySQL Database : Version ->8.0.19 MySQL Community Server
โฆJDK8 or later versions (Extremely tested on JDK8, JDK11 and JDK14)
Letโs follow below steps to develop a small web application and then apply UserDetailsService security into it.
Step#1: Createย a Spring Boot Starter Project in STS(Spring Tool Suite)
While creating Starter Project select โSpring Securityโ, โThymeleafโ, โSpring Webโ, โSpring Data JPAโ, โMySQL Driverโ, โLombokโ and โSpring Boot DevToolsโ as starter project dependencies. Even If you donโt know how to create a Spring Boot Starter Project, Kindly visit Internal Link.ย Also, if you want to know more about Lombok, then visit Internal Link on Lombok.
Step#2: Update database properties in application.properties file
Update application.properties to connect to MySQL DB accordingly. Please note that we can omit driver-class-name as Spring Boot will automatically find it from the database URL as shown below.
#application.properties
---------------------------------------------------------------------
#-------------------- server properties ---------------
server.port=8080
#--------------------- DB Connection ------------------
#AutoLoading of driver class since JDBC 4
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/testBootSecurity
spring.datasource.username=root
spring.datasource.password=devs
#--------------------JPA-ORM Properties-----------------
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.database-platform=org.hibernet.dialect.MySQL8Dialect
Step#3: Create User Entity & Repository classes
Now create User.java & UserRepositoty.java as below. Equally important, User.java has a variable โrolesโ of type List<String>. It will create a separate table in the database with two columns user_id and user_role accordingly. Further, @ElementCollection(fetch= FetchType.EAGER) indicates that while fetching User object, also fetch roles simultaneously. On the other hand, UserRepository extends โJpaRepositoryโ to taking advantage of inbuilt database operations.
User.java
package com.dev.springboot.security.UserDetailsService.model;
import java.util.List;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import lombok.Data;
@Data
@Entity
@Table(name="users")
public class User {
@Id
@GeneratedValue
@Column(name="user_id")
private Integer id;
@Column(name="user_name")
private String name;
@Column(name="user_passwd")
private String password;
@Column(name="user_email")
private String email;
@ElementCollection(fetch= FetchType.EAGER)
@CollectionTable(
name="roles",
joinColumns = @JoinColumn(name="user_id")
)
@Column(name="user_role")
private List<String> roles;
}
UserRepository.java
package com.dev.springboot.security.UserDetailsService.repo;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import com.dev.springboot.security.UserDetailsService.model.User;
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findUserByEmail(String email);
}
Step#4: Create AppConfig class to instantiate BCryptPasswordEncoder
As BCryptPasswordEncoder is a predefined class, hence we need to provide itโs instantiation code in AppConfig.java as a configuration class. Further, BCryptPasswordEncoder will be required to encode our password values in other classes.
AppConfig.java
package com.dev.springboot.security.UserDetailsService.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class AppConfig {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Step#5: Create Service Interface & Service Implementation class
Create Service Interface and Service Impl class as IUserService.java and UserServiceImpl.java accordingly as shown below. In fact, implementation of loadUserByUsername(String email) method in UserServiceImpl.java is the most important part of your UserDetailsService on the whole.
IUserService.java
package com.dev.springboot.security.UserDetailsService.service;
import com.dev.springboot.security.UserDetailsService.model.User;
public interface IUserService {
public Integer saveUser(User user);
}
UserServiceImpl.java
package com.dev.springboot.security.UserDetailsService.service.impl;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.dev.springboot.security.UserDetailsService.model.User;
import com.dev.springboot.security.UserDetailsService.repo.UserRepository;
import com.dev.springboot.security.UserDetailsService.service.IUserService;
@Service
public class UserServiceImpl implements IUserService, UserDetailsService{
@Autowired
private UserRepository userRepo;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Override
public Integer saveUser(User user) {
String passwd= user.getPassword();
String encodedPasswod = passwordEncoder.encode(passwd);
user.setPassword(encodedPasswod);
user = userRepo.save(user);
return user.getId();
}
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Optional<User> opt = userRepo.findUserByEmail(email);
org.springframework.security.core.userdetails.User springUser=null;
if(opt.isEmpty()) {
throw new UsernameNotFoundException("User with email: " +email +" not found");
}else {
User user =opt.get();
List<String> roles = user.getRoles();
Set<GrantedAuthority> ga = new HashSet<>();
for(String role:roles) {
ga.add(new SimpleGrantedAuthority(role));
}
springUser = new org.springframework.security.core.userdetails.User(
email,
user.getPassword(),
ga );
}
return springUser;
}
//Other Approach: Using Lambda & Stream API of Java 8
/*@Override
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
Optional<User> opt = userRepo.findUserByEmail(email);
if(opt.isEmpty())
throw new UsernameNotFoundException("User with email: " +email +" not found !");
else {
User user = opt.get();
return new org.springframework.security.core.userdetails.User(
user.getEmail(),
user.getPassword(),
user.getRoles()
.stream()
.map(role-> new SimpleGrantedAuthority(role))
.collect(Collectors.toSet())
);
}*/
}
Step#6: Create a UserController class
Subsequently, write a controller class for User as โUserController.javaโ which will control the user registration page.
UserController.java
package com.dev.springboot.security.UserDetailsService.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import com.dev.springboot.security.UserDetailsService.model.User;
import com.dev.springboot.security.UserDetailsService.service.IUserService;
@Controller
public class UserController {
@Autowired
private IUserService userService;
// Go to Registration Page
@GetMapping("/register")
public String register() {
return "registerUser";
}
// Read Form data to save into DB
@PostMapping("/saveUser")
public String saveUser(
@ModelAttribute User user,
Model model
)
{
Integer id = userService.saveUser(user);
String message = "User '"+id+"' saved successfully !";
model.addAttribute("msg", message);
return "registerUser";
}
}
Step#7: Write a Controller class to navigate through pages
In spite of UserController, write one more controller class and call it as โHomeController.javaโ. This class will be responsible to navigate through different pages.
HomeController.java
package com.dev.springboot.security.UserDetailsService.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/home")
public String getHomePage() {
return "homePage";
}
@GetMapping("/welcome")
public String getWelcomePage() {
return "welcomePage";
}
@GetMapping("/admin")
public String getAdminPage() {
return "adminPage";
}
@GetMapping("/emp")
public String getEmployeePage() {
return "empPage";
}
@GetMapping("/mgr")
public String getManagerPage() {
return "mgrPage";
}
@GetMapping("/hr")
public String getHrPage() {
return "hrPage";
}
@GetMapping("/common")
public String getCommonPage() {
return "commonPage";
}
@GetMapping("/accessDenied")
public String getAccessDeniedPage() {
return "accessDeniedPage";
}
}
Step#8: Write UI pages(Thymeleaf)ย
Below are the .html files for UI pages. Place these pages inside โsrc/main/resources/templatesโ folder accordingly.
registerUser.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>User Registration</title>
</head>
<body>
<h3>User Registration</h3>
<form action="saveUser" method="post">
<pre>
Name : <input type="text" name="name"/>
Email: <input type="text" name="email"/>
Password: <input type="password" name="password"/>
Role(s): <input type="checkbox" name="roles" value="Admin"/>Admin
<input type="checkbox" name="roles" value="Manager"/>Manager
<input type="checkbox" name="roles" value="HR"/>HR
<input type="checkbox" name="roles" value="Employee"/>Employee
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<input type="submit" value="Register"/>
</pre>
</form>
<div th:text="${msg}"></div>
</body>
</html>
homePage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3> welcome to the Home Page </h3>
This page is accessible to ALL.
</body>
</html>
welcomePage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3> Welcome Page after successful Login</h3>
<a th:href="@{/logout}" >LOGOUT</a>
</body>
</html>
adminPage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3> Admin Page </h3>
Welcome to Admin page.!!!
<a th:href="@{/logout}" >LOGOUT</a>
</body>
</html>
empPage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3> Employee Page </h3>
<a th:href="@{/logout}" >LOGOUT</a>
</body>
</html>
mgrPage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3> Manager Page </h3>
<a th:href="@{/logout}" >LOGOUT</a>
</body>
</html>
hrPage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3> HR Page </h3>
<a th:href="@{/logout}" >LOGOUT</a>
</body>
</html>
commonPage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3>You are not allowed to access this page. Please go to Welcome Page</h3>
<a th:href="@{/welcome}" >Welcome</a>
<a th:href="@{/logout}" >LOGOUT</a>
</body>
</html>
accessDeniedPage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3>You are not allowed to access this page. Please go to Welcome Page</h3>
<a th:href="@{/welcome}" >Welcome</a>
<a th:href="@{/logout}" >LOGOUT</a>
</body>
</html>
Step#9: Write SecurityConfig class
In the end, write the other important class as SecurityConfig.java which will extend a predefined class WebSecurityConfigurerAdapter.java and implement two configure() methods accordingly as given below.
SecurityConfig.java
package com.dev.springboot.security.UserDetailsService.config;
import org.springframework.beans.factory.annotation.Autowired;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService uds;
@Autowired
private BCryptPasswordEncoder encoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(uds).passwordEncoder(encoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/home","/register","/saveUser").permitAll()
.antMatchers("/welcome").authenticated()
.antMatchers("/admin").hasAuthority("Admin")
.antMatchers("/mgr").hasAuthority("Manager")
.antMatchers("/emp").hasAuthority("Employee")
.antMatchers("/hr").hasAuthority("HR")
.antMatchers("/common").hasAnyAuthority("Employeee,Manager,Admin")
.anyRequest().authenticated()
.and()
.formLogin()
.defaultSuccessUrl("/welcome",true)
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and()
.exceptionHandling()
.accessDeniedPage("/accessDenied");
}
}
Step#9A: Write SecurityConfig class Without Using WebSecurityConfigurerAdapter
As aforementioned, Spring Security 5.7.0-M2 onward, WebSecurityConfigurerAdapter has been deprecated. Hence, If you are using Spring Security 5.7.0-M2 or later versions, please update your implementation as shown in below code snippet.
SecurityConfig.java
package com.dev.springboot.security.UserDetailsService.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Autowired
private UserDetailsService uds;
@Autowired
private BCryptPasswordEncoder encoder;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/home","/register","/saveUser").permitAll()
.antMatchers("/welcome").authenticated()
.antMatchers("/admin").hasAuthority("Admin")
.antMatchers("/mgr").hasAuthority("Manager")
.antMatchers("/emp").hasAuthority("Employee")
.antMatchers("/hr").hasAuthority("HR")
.antMatchers("/common").hasAnyAuthority("Employeee,Manager,Admin")
.anyRequest().authenticated()
.and()
.formLogin()
.defaultSuccessUrl("/welcome",true)
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and()
.exceptionHandling()
.accessDeniedPage("/accessDenied")
.and()
.authenticationProvider(authenticationProvider());
return http.build();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(uds);
authenticationProvider.setPasswordEncoder(encoder);
return authenticationProvider;
}
}
Finally we have completed the coding part.
How to test the security enabled Application ?
Although the word โtestingโ looks very easy to a developer, but it is equally important as it provides the result of our implementation on the whole. While testing the application you should keep configure(HttpSecurity http) method of SecurityConfig class in front of you, then follow the steps given below:
1) Start the application : Right click on the project, then select โRun Asโ >> โSpring Boot Appโ.
2) Enter the registration page URL http://localhost:8080/register, then check if it is accessible to every one without even login to the application.
3) Enter the required field values and complete the registration process by clicking on the โRegisterโ button accordingly.
4) Now Enter any URL specific to the role you selected in registration. Suppose you entered URL http://localhost:8080/admin, then it should redirect you to the in-built Login page.
5) Enter the credentials(email id in place of username) and Login to the application. It will redirect you to the default success URL which is welcome page.
6) Now enter the URL http://localhost:8080/admin again, this time you will be able to access the admin page.
7) Repeat the above steps for other roles as well.
Additionally, as mentioned above keep the code in front of you and test each scenario subsequently.
Summary
After going through all the theoretical & examples part of โHow to implement Security in Spring Boot using UserDetailsService?โ, finally, we are able to implement web security in a Spring Boot project. Of course, In this article we have covered the third way of implementing security feature. Similarly, we will talk about some more ways of security like REST security in our upcoming articles. If there is any change in the future, we will update the same accordingly. If you want to learn more about Spring Security, kindly visit spring.io documentation. Moreover, Feel free to provide your comments in the comments section.
This is really interesting, Youโre a very skilled blogger. Iโve joined your rss feed and look forward to seeking more of your excellent post. Also, I have shared your web site in my social networks!
Thanks for your motivation to do better in future posts as well. Also, Thanks for sharing the web site.
Heya are using WordPress for your site platform? Iโm new to the blog world but Iโm trying to get started and create my own. Do you need any html coding expertise to make your own blog? Any help would be really appreciated!
Request you to please put your comments which are related to the topic so that other readers also get benefitted. Topic is not related to โHow to make your own blog?โ at all.
Nice Article with nice explanation. Good Job !
Great Post. A beginner can also understand all about the Topic in one go.
Great Tutorialโฆโฆ.
Really Fantastic website as a whole.
Really very very informative post. Unbelievable to me !
Nicely explained. You start your articles with basics that is even the best thing for readers to make the concepts stronger.
Very nicely & clearly explained.
I liked the way you explain the concepts, from basic to advancedโฆ..Looking forward to check your upcoming posts.
Good website to learn java .thanks
Thanks very nice blog!
Hi there! Someone in my Facebook group shared this site with us so I came to take a look.
Iโm definitely loving the information. Iโm bookmarking
and will be tweeting this to my followers!
Fantastic blog and superb style and design.
Hello There. I found your weblog using msn. That is a very well written article. I will make sure to bookmark it and come back to read more of your helpful info. Thank you for the post. Iโll definitely return.
You completed a number of fine points there. I did a search on the topic and found most folks will go along with with your blog.
Hey there, I seriously like your amazing internet site! This is a nice posting. My family and i look forward to reading more exciting information in which youll be publishing within the forthcoming. Weโve found out a lot by this. Thanks a ton. -Olene Griffins
I just wanted to throw you a big thank you โ you cleared up some things for me!
Awesome post.
I believe this is one of the most significant info for me.
And i am glad studying your article. However wanna
observation on some general things, The web site style is
perfect, the articles is in point of fact nice : D. Excellent process,
cheers
Im obliged for the post. Fantastic.
Luar biasa , pelajaran yang sangat menarik dan bermanfaat ,
Terimakasih
Hey , very nice explanation . after reading and watching multiple articles. I can say this is one of the finest explanation with diagrams ,theory and codes.
Hatโs off
Thanks everyone for all your valuable feedback. It will motivate us to do even better in future articles.
Now the code is updated as per the changes in Spring Security 5.7.0-M2 API i.e. Without Using WebSecurityConfigurerAdapter.