How to implement Security in Spring Boot Project? Spring Boot java Spring Spring Boot 3 by devs5003 - February 19, 2023March 15, 20245 Last Updated on March 15th, 2024Now a days, almost every client demands for implementation of powerful security feature in real time application. Demand of security feature is very valid to maintain confidentiality, integrity and availability. There are many types of security in the real world, but we as a developer will focus on the Application/Software Security. Furthermore, in Application Security, our job is to ensure basically two things. First, only valid user can access the application. Second, If the user is valid, he/she can access only permitted data/information in that application. I consider, there is nothing to explain more about them as you must already be aware of these two terminologies i.e. Authentication & Authorization. You might already have guessed what we will discuss in our current topic ‘How to implement Security in Spring Boot Project?’ In this article, we will start with exploring basic fundamentals. Following step by step, we will end it until we feel confident in implementing Security features in a Spring Boot Application. Accordingly, Let’s start discussing about ‘How to implement Security in Spring Boot Project?’ step by step. A Series of tutorials on Spring Boot Security are on Spring Boot Tutorials page. We have covered the example of ‘How to implement Security in Spring Boot Project?’ for both versions: With WebSecurityConfigurerAdapter and Without WebSecurityConfigurerAdapter in this article. Moreover, the example of ‘How to implement Security in Spring Boot Project?’ Using Spring Boot 3.0 and higher versions is also covered. Table of Contents Toggle What will you learn from this article?Why do we need Security in an Application?How does security work internally in a Spring Boot Application ?How many types of authorization are used in Spring Boot Application?1) permitAll2) authenticated3) hasAuthority4) hasAnyAuthorityWhat are the various ways to implement security in a Spring Boot Web Application?In-Memory SecurityUsing Database(JDBC) Using UserDetailsServiceWhat are the steps to implement web security in Spring Boot Application?Example of How to implement in-memory authentication securitySoftware/Technologies UsedStep#1 : Create a Spring Boot Starter Project in STS(Spring Tool Suite)Step#2 : Write a Controller class Step#3 : Write UI pages(Thymeleaf) Step#4 : Write SecurityConfig classStep#4A: Code For versions lower than Spring Security 5.7.0Step#4B: Code For versions higher than Spring Security 5.7 and lower than Spring Security 6.0Step#4C: Code For versions Spring Security 6.0.0 and higher (Spring Boot 3.0+)Example of How to implement JDBC authentication securitySoftware/Technologies UsedStep#1 : Insert some dummy records in database Step#1A : Create encoded password values by using BCryptPasswordEncoderOutputStep#1B : create a database and insert dummy recordsStep#2 : Create a Spring Boot Starter Project in STS(Spring Tool Suite)Step#3 : Copy Controller class & UI pages from previous ExampleStep#4 : Create AppConfig.java to create object of BCryptPasswordEncoderStep#5 : Update database properties in application.properties fileStep#6 : Update SecurityConfig.javaStep#6A: Code For versions lower than Spring Security 5.7.0Step#6B: Code For versions higher than Spring Security 5.7.0 and lower than Spring Security 6.0.0Step#6C: Code For versions Spring Security 6.0.0 and higher (Spring Boot 3.0+)How to test the security enabled Application ?How to implement Security in Spring Boot Project? : Spring Boot 3.0 OnwardFAQHow to disable Security feature of the Application?What are the key components of Spring Boot Security?Can I integrate Spring Boot Security with various authentication mechanisms?How can I customize the login page in a Spring Boot Security application?What is role-based access control (RBAC) in Spring Boot Security?Summary What will you learn from this article? 1) Why do we need to implement security in a Spring Boot application? 2) How does security work internally in a Spring Boot application? 3) What is a role of javax.servlet.Filter in implementing security in a Spring Boot application? 4) How many types of authorization are used in a Spring Boot Project? 5) How many ways are there to implement security in a Spring Boot Project? 6) What are the steps to implement web security in a Spring Boot Project? 7) Also, How to use @EnableWebSecurity, @Configuration, @Bean in a Spring Boot Project? 8) Example of How to implement in-memory authentication security 9) Example of How to implement JDBC authentication security 10) How to work with Thymeleaf in Spring Boot Project ? 11) How to test the security-enabled feature ? 12) On the contrary, How to disable security feature of the application? 13) Last but not the least you will learn “How to implement Security in Spring Boot Project?” using WebSecurityConfigurerAdapter and Without using WebSecurityConfigurerAdapter. Why do we need Security in an Application? Now a day’s data are at most risk as malicious attacks moving their focus to applications/software and mobiles/devices from operating systems & networks. Also, from the business/client perspective, application security plays an important role in maintaining trust, building brand image & mitigating risks. In fact, without any one of these don’t think about a successful business. In conclusion, it does not matter if you are creating the app for in-house use, selling purpose, or buying purpose, Security is the most important feature for each & every app. As per the most recent Verizon Data Breach Investigations Report-2020, 43% of all data breaches were attacks on web applications. This represented a doubling of the number from 2019. In addition, 86% of all breaches were financially motivated. How does security work internally in a Spring Boot Application ? Fundamentally, spring security works on a concept called JAAS(Java Authentication and Authorization Services). In brief, it works on Filter (javax.servlet.Filter) concept. We all know that we can use the Filters if we want to apply some pre-processing logic before a servlet request. The same concept has been applied to implement security features in Spring boot projects as well. DelegatingFilterProxy is a predefined class under package org.springframework.web.filter provided by Spring Security module which acts as a filter here. As shown in the diagram below when a user sends a request to the application, it passes through a security filter before going to DispatcherServlet. If user validates the security of this filter, then only the request will go to DispatcherServlet to serve the user’s purpose. How many types of authorization are used in Spring Boot Application? There are four mostly used types of authorization implementation available. They are : 1) permitAll permitAll represents that No need of any authorization to access current page. Example URLs: /login, /home, /contactUs, /aboutUs ..etc. 2) authenticated It represents that Login(username/password) is Required & no authorization(role based access) is required. Examle URLs: /updateUserDetails, /inbox, /settings, ..etc. 3) hasAuthority hasAuthority represents that user should have both authentication and role based authorization access. Example URLs+role: /approveRequest + MANAGER, /blockUser + ADMIN, /addUser + ADMIN …etc. 4) hasAnyAuthority It represents that user should have authentication and multiple role based authorization access. It’s like Manager & HR both roles have access to a particular page. Example URLs+role: /approveRequest + (MANAGER & HR) What are the various ways to implement security in a Spring Boot Web Application? Briefly, there are the three most common ways to implement security in a Spring Boot web application. They are In-Memory Security In this type of implementation, we store data in RAM (in-memory) and validate data when there is a request. We use this method in test or development environment. This method is not recommended in production applications. Using Database(JDBC) In this type of implementation, we store data in the database and validate data/login when a request arrives. But it works based on SQL queries provided by the programmer. Using UserDetailsService We store data in the database and validate data when a request comes. But UserDetailsService works based on ORM(Spring Data JPA). In short, UserDetailsService is an interface provided by the Spring Security module. After entering the username in Login form, when we click on login button this service is called. Subsequently, It locates the user based on the provided username. It contains a method loadUserByUsername(String username) which returns UserDetails object. Furthermore, the UserDetails object provides us the username. What are the steps to implement web security in Spring Boot Application? Below are the steps: 1) Write a class as ‘SecurityConfig.java’ that extends a predefined abstract class WebSecurityConfigurerAdapter.java 2) Apply annotations @Configuration and @EnableWebSecurity on top of ‘SecurityConfig.java’ accordingly. Needless to say, annotation @EnableWebSecurity is for enabling the security feature in web application. 3) Override below two methods to implement authentication & authorization logics simultaneously. configure(AuthenticationManagerBuilder auth) configure(HttpSecurity http) 4) Furthermore, Inject other objects dependency(if any), by using @Autowired like DataSource, BCryptPasswordEncoder etc. and use where you need them. 5) Equally important, Write controller classes and view pages consequently as needed. 6)  In the end, update database properties in application.properties file if you are not implementing in-memory authentication. Note: Spring Security 5.7.0-M2 onward, WebSecurityConfigurerAdapter has been deprecated. In order to learn the new way of implementing custom configuration class, visit a separate article on Spring Security without WebSecurityConfigurerAdapter. Example of How to implement in-memory authentication security For example, Let’s consider an application of a small organization where we have three roles : EMPLOYEE, MANAGER and ADMIN. In addition, we will have role based restricted access to some particular pages. On the one hand, some pages will be accessible to multiple roles and on the other hand some with no restrictions(accessible to all roles). Moreover, we will use thymeleaf to create pages. Additionally, we will have a controller class to serve the user’s request. Software/Technologies Used ♦STS (Spring Tool Suite) : Version-> 4.7.1.RELEASE ♦JDK14 (JDK8 or later versions are sufficient) Step#1 : Create a Spring Boot Starter Project in STS(Spring Tool Suite) While creating Starter Project, select ‘Spring Security’, ‘Thymeleaf’, ‘Spring Web’ and ‘Spring Boot DevTools’ as starter project dependencies. In order to know ‘how to create Spring Boot Starter Project?’, kindly visit Internal Link. Step#2 : Write a Controller class Please check below code as a Controller class. HomeController.java package com.dev.springboot.security.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;@Controllerpublic 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("/common") public String getCommonPage() { return "commonPage"; } @GetMapping("/accessDenied") public String getAccessDeniedPage() { return "accessDeniedPage"; }} Step#3 : Write UI pages(Thymeleaf) Below files are UI pages. So, place them inside ‘src/main/resources/templates’ folder only. 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 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>Only Admins are allowed to access this 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> 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> COMMON Page </h3>Both Manager & Employee are allowed to access this page. !<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#4 : Write SecurityConfig class This class is the most important with respect to implementing security features that contains all security related logics. As shown in the code example below, we use ‘{noop}’ before password value if we don’t want to encode the password. Step#4A: Code For versions lower than Spring Security 5.7.0 SecurityConfig.java package com.dev.springboot.security;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.web.util.matcher.AntPathRequestMatcher;@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // {noop} => No operation for password encoder (no password encoding needed) auth.inMemoryAuthentication().withUser("devs").password("{noop}devs").authorities("ADMIN"); auth.inMemoryAuthentication().withUser("ns").password("{noop}ns").authorities("EMPLOYEE"); auth.inMemoryAuthentication().withUser("vs").password("{noop}vs").authorities("MANAGER"); } @Override protected void configure(HttpSecurity http) throws Exception { //declares which Page(URL) will have What access type http.authorizeRequests() .antMatchers("/home").permitAll() .antMatchers("/welcome").authenticated() .antMatchers("/admin").hasAuthority("ADMIN") .antMatchers("/emp").hasAuthority("EMPLOYEE") .antMatchers("/mgr").hasAuthority("MANAGER") .antMatchers("/common").hasAnyAuthority("EMPLOYEE","MANAGER") // Any other URLs which are not configured in above antMatchers // generally declared aunthenticated() in real time .anyRequest().authenticated() //Login Form Details .and() .formLogin() .defaultSuccessUrl("/welcome", true) //Logout Form Details .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) //Exception Details .and() .exceptionHandling() .accessDeniedPage("/accessDenied") ; }} Step#4B: Code For versions higher than Spring Security 5.7 and lower than Spring Security 6.0 As WebSecurityConfigurerAdapter has been deprecated from Spring Security 5.7.0-M2 as per an announcement posted in the Spring Official website, on 21st Feb, 2022, we will write SecurityConfig class without using WebSecurityConfigurerAdapter as shown below: SecurityConfig.java package com.dev.springboot.security;import java.util.ArrayList;import java.util.List;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.EnableWebSecurity;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.provisioning.InMemoryUserDetailsManager;import org.springframework.security.web.SecurityFilterChain;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;@Configuration@EnableWebSecuritypublic class SecurityConfig { @Bean protected InMemoryUserDetailsManager configAuthentication() { List<UserDetails> users = new ArrayList<>(); List<GrantedAuthority> adminAuthority = new ArrayList<>(); adminAuthority.add(new SimpleGrantedAuthority("ADMIN")); UserDetails admin= new User("devs", "{noop}devs", adminAuthority); users.add(admin); List<GrantedAuthority> employeeAuthority = new ArrayList<>(); adminAuthority.add(new SimpleGrantedAuthority("EMPLOYEE")); UserDetails employee= new User("ns", "{noop}ns", employeeAuthority); users.add(employee); List<GrantedAuthority> managerAuthority = new ArrayList<>(); adminAuthority.add(new SimpleGrantedAuthority("MANAGER")); UserDetails manager= new User("vs", "{noop}vs", managerAuthority); users.add(manager); return new InMemoryUserDetailsManager(users); } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { //declares which Page(URL) will have What access type http.authorizeRequests() .antMatchers("/home").permitAll() .antMatchers("/welcome").authenticated() .antMatchers("/admin").hasAuthority("ADMIN") .antMatchers("/emp").hasAuthority("EMPLOYEE") .antMatchers("/mgr").hasAuthority("MANAGER") .antMatchers("/common").hasAnyAuthority("EMPLOYEE","MANAGER") // Any other URLs which are not configured in above antMatchers // generally declared aunthenticated() in real time .anyRequest().authenticated() //Login Form Details .and() .formLogin() .defaultSuccessUrl("/welcome", true) //Logout Form Details .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) //Exception Details .and() .exceptionHandling() .accessDeniedPage("/accessDenied") ; return http.build(); }} Step#4C: Code For versions Spring Security 6.0.0 and higher (Spring Boot 3.0+) From Spring Security 6.0 (released in November, 2022), the WebSecurityConfigurerAdapter is completely removed from the Spring Security API. It has also impacted the newly released Spring Boot 3.0 in November, 2022. Hence, if you are using Spring Framework 6.0+ or Spring Boot 3.0+, in either case, your implementation of SecurityConfig.java should look like below. Additionally, you can also check the Spring Security related changes in Spring Framework 6.0. SecurityConfig.java package com.dev.springboot.security;import java.util.ArrayList;import java.util.List;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.EnableWebSecurity;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.provisioning.InMemoryUserDetailsManager;import org.springframework.security.web.SecurityFilterChain;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;@Configuration@EnableWebSecuritypublic class SecurityConfig { @Bean protected InMemoryUserDetailsManager configAuthentication() { List<UserDetails> users = new ArrayList<>(); List<GrantedAuthority> adminAuthority = new ArrayList<>(); adminAuthority.add(new SimpleGrantedAuthority("ADMIN")); UserDetails admin= new User("devs", "{noop}devs", adminAuthority); users.add(admin); List<GrantedAuthority> employeeAuthority = new ArrayList<>(); adminAuthority.add(new SimpleGrantedAuthority("EMPLOYEE")); UserDetails employee= new User("ns", "{noop}ns", employeeAuthority); users.add(employee); List<GrantedAuthority> managerAuthority = new ArrayList<>(); adminAuthority.add(new SimpleGrantedAuthority("MANAGER")); UserDetails manager= new User("vs", "{noop}vs", managerAuthority); users.add(manager); return new InMemoryUserDetailsManager(users); } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { //declares which Page(URL) will have What access type http.authorizeHttpRequests() .requestMatchers("/home").permitAll() .requestMatchers("/welcome").authenticated() .requestMatchers("/admin").hasAuthority("ADMIN") .requestMatchers("/emp").hasAuthority("EMPLOYEE") .requestMatchers("/mgr").hasAuthority("MANAGER") .requestMatchers("/common").hasAnyAuthority("EMPLOYEE","MANAGER") // Any other URLs which are not configured in above antMatchers // generally declared aunthenticated() in real time .anyRequest().authenticated() //Login Form Details .and() .formLogin() .defaultSuccessUrl("/welcome", true) //Logout Form Details .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) //Exception Details .and() .exceptionHandling() .accessDeniedPage("/accessDenied") ; return http.build(); }} Note: In the code above, observe the API changes in Spring Security 6.0: antMatchers() replaced by requestMatchers(), authorizeRequests() replaced by authorizeHttpRequests(). Your project structure will look like below snapshot. Example of How to implement JDBC authentication security In this method of authentication we validate credentials and roles from existing values in database. Also, we will work on password encryption logic as well in this example. First of all we will insert some dummy data in the database, then test the security feature accordingly. In the final analysis, If we compare the functionality of the previous example from this is that we will save user credentials & roles into the database rather than RAM. Also, we will have additional code for implementing password encryption logic in this example. So all files from the previous example will also be valid in this example. Additionally, we will have one config class to create object of BCryptPasswordEncoder to encode the password and also entries of database properties in application.properties to connect with the database. Needless to say, the implementation of SecurityConfig class will differ this time. Software/Technologies Used ♦ STS (Spring Tool Suite) : Version-> 4.7.1.RELEASE ♦ MySQL Database : Version ->8.0.19 MySQL Community Server ♦ JDK14 (JDK8 or later versions are sufficient) Step#1 : Insert some dummy records in database Please note that this step is required only for testing purpose. If you already have a database created with user credentials and roles mapping recently, ignore this step. In Step#1A we will create some encoded values of password, then we insert them into database in Step#1B. Step#1A : Create encoded password values by using BCryptPasswordEncoder We will use BCryptPasswordEncoder to generate some encoded password values as below BCryptPasswordEncoderTest.java package com.dev.springboot.security.util;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;public class BCryptPasswordEncoderTest { public static void main(String[] args) { BCryptPasswordEncoder bpe = new BCryptPasswordEncoder(); String encodedPWD = bpe.encode("devs@A!5003"); System.out.println(encodedPWD); }} Output $2a$10$qnOB2PH1CqRvw8f5epvHzOlrounRkVGi.Y5ho6ENdmj/C1DmPdAsy Step#1B : create a database and insert dummy records Execute MySQL DB Commands as shown below: To create the database as 'testbootsecurity' ♦ create database testbootsecurity; To take 'testbootsecurity' in use: ♦ use testbootsecurity; To create the user table: ♦ create table user (user_id int, user_name varchar(30), user_pwd varchar(100), user_role varchar(20), user_enabled int); To check the description of user table: ♦ desc user; INSERT INTO user values(501,'devs','$2a$10$qnOB2PH1CqRvw8f5epvHzOlrounRkVGi.Y5ho6ENdmj/C1DmPdAsy','ADMIN',1); INSERT INTO user values(502,'ns','$2a$10$mmUMC5ZwoVnEQYV7/R6m.uWWtj7EiIo3lKasBObkOCc12huVUWpMC','EMPLOYEE',1); INSERT INTO user values(503,'vs','$2a$10$kqEC/fhQ7SNDhnncOQ9pb.yXXxJ/c7a1SQx2QPNZ.47fUmvF3Wb.i','MANAGER',1); ♦ select * from user; (To check if values are inserted into DB) In addition, we will require below two queries in implementing configure(AuthenticationManagerBuilder auth) method of SecurityConfig.java class. Query#1 : Retrieve username,password,enabled using username ; ♦ select user_name,user_pwd,user_enabled from user where user_name=?; Query#2 : Retrieve username,role using username; ♦ select user_name,user_role from user where user_name=?; Step#2 : Create a Spring Boot Starter Project in STS(Spring Tool Suite) While creating Starter Project select ‘Spring Security’, ‘Thymeleaf’, ‘Spring Web’, ‘JDBC API’, ‘MySQL Driver’ and ‘Spring Boot DevTools’ as starter project dependencies. Step#3 : Copy Controller class & UI pages from previous Example Copy HomeController.java and also all thymeleaf pages from previous example. Step#4 : Create AppConfig.java to create object of BCryptPasswordEncoder Create AppConfig.java as below. We will require object of BCryptPasswordEncoder while implementing SecurityConfig.java class. AppConfig.java package com.dev.springboot.security.jdbc.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;@Configurationpublic class AppConfig { @Bean public BCryptPasswordEncoder encode() { return new BCryptPasswordEncoder(); }} Step#5 : Update database properties in application.properties file Update application.properties to connect to MySQL DB as below. Please note that we can omit driver-class-name as Spring Boot will automatically find it from database URL. #application.properties ------------------------------------------------------------------- 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 Step#6 : Update SecurityConfig.java Copy SecurityConfig.java from previous example and update configure(AuthenticationManagerBuilder auth) method as below. Step#6A: Code For versions lower than Spring Security 5.7.0 SecurityConfig.java package com.dev.springboot.security.jdbc.config;import javax.sql.DataSource;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.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private BCryptPasswordEncoder passwordEncoder; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication() .dataSource(dataSource) //creates database connection .usersByUsernameQuery("select user_name,user_pwd,user_enabled from user where user_name=?") .authoritiesByUsernameQuery("select user_name,user_role from user where user_name=?") .passwordEncoder(passwordEncoder); } @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/home").permitAll() .antMatchers("/welcome").authenticated() .antMatchers("/admin").hasAuthority("ADMIN") .antMatchers("/emp").hasAuthority("EMPLOYEE") .antMatchers("/mgr").hasAuthority("MANAGER") .anyRequest().authenticated() .and() .formLogin() .defaultSuccessUrl("/welcome",true) .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .and() .exceptionHandling() .accessDeniedPage("/accessDenied") ; }} Step#6B: Code For versions higher than Spring Security 5.7.0 and lower than Spring Security 6.0.0 As WebSecurityConfigurerAdapter has been deprecated from Spring Security 5.7.0-M2 as per an announcement posted in the Spring Official website, on 21st Feb, 2022, we will write SecurityConfig class without using WebSecurityConfigurerAdapter as shown below: SecurityConfig.java package com.dev.springboot.security.jdbc.config;import javax.sql.DataSource;import org.springframework.beans.factory.annotation.Autowired;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.EnableWebSecurity;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.factory.PasswordEncoderFactories;import org.springframework.security.provisioning.JdbcUserDetailsManager;import org.springframework.security.provisioning.UserDetailsManager;import org.springframework.security.web.SecurityFilterChain;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;@Configuration@EnableWebSecuritypublic class SecurityConfig { @Autowired private DataSource dataSource; @Autowired private BCryptPasswordEncoder passwordEncoder; @Bean public UserDetailsManager authenticateUsers() { UserDetails user = User.withUsername("devs"). password(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("password")).build(); JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource); users.setAuthoritiesByUsernameQuery("select user_name,user_pwd,user_enabled from user where user_name=?"); users.setUsersByUsernameQuery("select user_name,user_role from user where user_name=?"); users.createUser(user); return users; } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/home").permitAll() .antMatchers("/welcome").authenticated() .antMatchers("/admin").hasAuthority("ADMIN") .antMatchers("/emp").hasAuthority("EMPLOYEE") .antMatchers("/mgr").hasAuthority("MANAGER") .anyRequest().authenticated() .and() .formLogin() .defaultSuccessUrl("/welcome",true) .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .and() .exceptionHandling() .accessDeniedPage("/accessDenied") ; return http.build(); }} Step#6C: Code For versions Spring Security 6.0.0 and higher (Spring Boot 3.0+) From Spring Security 6.0 (released in November, 2022), the WebSecurityConfigurerAdapter is completely removed from the Spring Security API. It has also impacted the newly released Spring Boot 3.0 in November, 2022. Hence, if you are using Spring Framework 6.0+ or Spring Boot 3.0+, in either case, your implementation of SecurityConfig.java should look like below. Additionally, you can also check the Spring Security related changes in Spring Framework 6.0. SecurityConfig.java package com.dev.springboot.security.jdbc.config;import javax.sql.DataSource;import org.springframework.beans.factory.annotation.Autowired;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.EnableWebSecurity;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.factory.PasswordEncoderFactories;import org.springframework.security.provisioning.JdbcUserDetailsManager;import org.springframework.security.provisioning.UserDetailsManager;import org.springframework.security.web.SecurityFilterChain;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;@Configuration@EnableWebSecuritypublic class SecurityConfig { @Autowired private DataSource dataSource; @Autowired private BCryptPasswordEncoder passwordEncoder; @Bean public UserDetailsManager authenticateUsers() { UserDetails user = User.withUsername("devs"). password(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("password")).build(); JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource); users.setAuthoritiesByUsernameQuery("select user_name,user_pwd,user_enabled from user where user_name=?"); users.setUsersByUsernameQuery("select user_name,user_role from user where user_name=?"); users.createUser(user); return users; } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests() .requestMatchers("/home").permitAll() .requestMatchers("/welcome").authenticated() .requestMatchers("/admin").hasAuthority("ADMIN") .requestMatchers("/emp").hasAuthority("EMPLOYEE") .requestMatchers("/mgr").hasAuthority("MANAGER") .anyRequest().authenticated() .and() .formLogin() .defaultSuccessUrl("/welcome",true) .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .and() .exceptionHandling() .accessDeniedPage("/accessDenied") ; return http.build(); }} Note: In the code above, observe the API changes in Spring Security 6.0: antMatchers() replaced by requestMatchers(), authorizeRequests() replaced by authorizeHttpRequests(). How to test the security enabled Application ? After a lot of theory and coding steps simultaneously, its time to test the ‘How to implement Security in Spring Boot Project?’. Please follow below steps. 1) Start the application, subsequently Right click on the project, then select “Run As’ >> ‘Spring Boot App’. 2) Enter the home page URL http://localhost:8080/home, then check if it is accessible to everyone without even login to the application. 3) Enter the admin page URL http://localhost:8080/admin, then it should be redirected to inbuilt login page (provided by Spring Security) 4) Login with providing admin credentials, you will be redirected to welcome page. 5) Enter the URL http://localhost:8080/admin, then you will be able to see the admin page now. 6) As you are logged in with admin credentials, you can see all the pages by hitting the other pages URLs also. Repeat the above steps subsequently for other roles as well & check whether user can access the page as per the granted roles. How to implement Security in Spring Boot Project? : Spring Boot 3.0 Onward Spring Boot 3.0 comes with major API level changes in the Spring Security module. Hence, if you are using Spring Boot 3.0 or later versions, you need to follow below guidelines along with using JDK 17. 1) In SecurityConfig.java: Use authorizeHttpRequests() in place of authorizeRequests() Use requestMatchers() in place of antMatchers() Use RegexRequestMatchers() in place of regexMatchers() 2) In Entity class: In import statements, use ‘jakarta’ in place of ‘javax’. For example: Use ‘jakarta.persistence.Entity;’ in place of ‘javax.persistence.Entity;’. FAQ How to disable Security feature of the Application? Equally important, sometimes we need to disable the security feature, particularly in development & test environment to avoid entering credentials again & again. For that we can comment below two dependencies in your pom.xml file accordingly. <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> --> What are the key components of Spring Boot Security? The key components of Spring Boot Security are authentication providers, user details services, security filters, access control rules, and login/logout features. Can I integrate Spring Boot Security with various authentication mechanisms? Yes, Spring Boot Security supports various authentication mechanisms, such as form-based authentication, HTTP Basic authentication, OAuth 2.0, and more. We can choose the one that suits our project’s requirements. How can I customize the login page in a Spring Boot Security application? We can customize the login page by creating a custom HTML login form and specifying its URL in the Spring Security configuration. Spring Boot makes it easy to define custom login pages. What is role-based access control (RBAC) in Spring Boot Security? Role-based access control is a security feature in Spring Boot that assigns roles to users and defines access permissions based on these roles. It offers us to control who can access specific parts of our application based on roles. Summary Subsequently, going through all the theoretical & examples part of ‘How to implement Security in Spring Boot Project?’, finally, we are able to implement web security in a Spring Boot project. Of course, in this article we have covered two ways of implementing security feature. Furthermore, we can go through UserDetailsService (the third way of implementing security) in a separate article. Also, for complete tutorials on Spring Boot Security visit here. If there is any update in the future, we will update the same accordingly. Also Feel free to provide your comments in below comments section. Related
It is actually the best article I’ve seen about Spring Security. I was stuck trying to understand it and I got it now. Thank you so much for the time spent writing this article. **Found it on LinkedIn Spring Users group Reply