You are here
Home > Spring Boot >

How to implement Security in Spring Boot Project?

How to implement Security in Spring Boot Project?Now a days, almost every client demands for implementation of 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 our world which is 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 learning with basic fundamentals. Following step by step, we will stop it becoming 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.

Table of Contents (Click on links below to navigate)

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?”

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 ?

Fundamentaly, 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.

SpringSecurity1

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 comes. 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:

SpringSecurity2
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.

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;

@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("/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.

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
@EnableWebSecurity
public 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")
		;
	}
}

Your project structure will look like below snapshot.

How to implement Security in Spring Boot Project?

Example of How to implement JDBC authentication security

In this method of authenticaton 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("[email protected]!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;

@Configuration
public 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.

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
@EnableWebSecurity
public 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")
		;
		
	}
}

 

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 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>
-->

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 other article. Also, for complete tutorials on Spring Boot Security visit here. If there is any update in future, we will update the same accordingly. Also Feel free to provide your comments in below comments section.

close

5 thoughts on “How to implement Security in Spring Boot Project?

  1. 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

Leave a Reply

Top