➤ How to Code a Game
➤ Array Programs in Java
➤ Java Inline Thread Creation
➤ Java Custom Exception
➤ Hibernate vs JDBC
➤ Object Relational Mapping
➤ Check Oracle DB Size
➤ Check Oracle DB Version
➤ Generation of Computers
➤ XML Pros & Cons
➤ Git Analytics & Its Uses
➤ Top Skills for Cloud Professional
➤ How to Hire Best Candidates
➤ Scrum Master Roles & Work
➤ CyberSecurity in Python
➤ Protect from Cyber-Attack
➤ Solve App Development Challenges
➤ Top Chrome Extensions for Twitch Users
➤ Mistakes That Can Ruin Your Test Metric Program
Spring Boot Security | Security is applied through the JAAS concept. JAAS understands Java Authentication and Authorization. What is Authentication and Authorization?
Authentication: Read usernames/passwords, and validate them.
Authorization: Role management.
Example:- Bank Application. All people have to login through username/password to use the application, this process is called Authentication. Application has different types of roles like Manager, Clerk, and User. Based on the role they can perform different actions:-
- User: View Balance, Open FD/RD, Transfer Money, etc..
- Manager: Approve loans, View Employees, View Branch Information, etc.
- Clerk: Deposits/Withdraws, print statements, etc.
Accessing different resources or actions based on the role is the process of Authorization. In spring Authentication and Authorization concept is applied using Spring Security.
Authentication vs Authorization
Authentication and authorization are two fundamental concepts in security, often used together but serving different purposes.
Authentication
- Purpose: Verifies the identity of a user or system.
- Process: Involves checking credentials like usernames, passwords, biometrics, or security tokens.
- Example: When you log into a website using your username and password, the system checks if your credentials match its records to confirm your identity.
Authorization
- Purpose: Determines what resources or actions the authenticated user is allowed to access.
- Process: Involves setting permissions and access levels for different resources.
- Example: After logging in, you might have access to your account settings but not to the admin panel, which is restricted to users with higher privileges.
Key Differences
- Authentication is about verifying identity, while authorization is about granting permissions.
- Authentication always comes before authorization. You must first prove your identity before the system can decide what you are allowed to do.
How Security Works in Spring
Spring web application internally uses Servlet.
Filter(I) [javax.servlet]
:- It is used to execute PRE-PROCESSING logic over the request object (before going to servlet) and POST-PROCESSING logic over the response object (after coming from Servlet). Only PRE-PROCESSING or POST-PROCESSING is also possible.DelegatingFilterProxy(C) [org.springframework.web.filter]
:- This is a predefined filter given by Spring Security. It implements Filter(I) [javax.servlet]. It will process the request for JAAS.

All security is implemented using a concept filter through DelegatingFilterProxy with will do authentication and authorization services. Then control goes to Dispatcher Servlet to process the request. Dispatcher Servlet gives a response either success or failure.
Authorization Type
When we develop any application then not all pages need security. For example:- Login page, Create new account page, Contact page, About Us page. These pages should be accessible to everyone without Authorization. Few pages can be accessed after login but every logged-in user can access that, and role validation is not required. Example:- profile-edit page, settings page.
Authorization Type:-
permitAll
: No security is required to access the page/path. Example URLs: /loging, /home, /contactUs, etc.authenticated
: Login is required, but no role is required. Example:- /inbox, /settings, /edit-profile etc.hasRole
: Log in required, and the matching role required. Example:- /approveLoan + Manager, /blockUser + Admin.hasAnyRole
: Login is required, and any matching role is required. Example:- /showBankStatement + Manager/Clerk
HttpStatus Codes
- In case of request URL comes under authenticated type and the Login person has provided an invalid username/password, then HttpStatus code:- UNAUTHORIZED(401, “Unauthorized”).
- In case of request URL comes under the has-role type and Login success, but the Role is not matching, then HTTP Status code:- FORBIDDEN(403, “Forbidden”).
API Details
In recent versions of Spring Security, specifically starting from version 5.7.0-M2, the WebSecurityConfigurerAdapter class has been deprecated. This change encourages a more component-based approach to configuring security.
Instead of extending WebSecurityConfigurerAdapter, you now define security configurations using beans. Here’s how you can do it:-
- Define a UserDetailsService Bean: This bean sets up user details for authentication.
- Define a SecurityFilterChain Bean: This bean configures the HTTP security (authorization).
Create a spring boot starter project with Spring Security dependencies.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorizeRequests -> authorizeRequests
.anyRequest()
.authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
return http.build();
}
@Bean
UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder.encode("password"))
.roles("USER", "ADMIN")
.build();
return new InMemoryUserDetailsManager(user);
}
}
We can add the following details in securityFilterChain:-
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// URL AccessTypes
// Login Form Details
// Logout Details
// Exception Details
}
PasswordEncoder
- Encode: Convert readable data into unreadable format. Example:- Hello => hign%53jhv4
- Decode: Encoded data converted back into readable format. Example:- hign%53jhv4 => Hello
The password in the database will be saved after encoding through PasswordEncoder(I). PasswordEncoder is an interface given by Spring Security. PasswordEncoder has many implementation classes, and BCryptPasswordEncoder is one of them which uses the BCrypt strong hashing function.
In Spring Security programming PasswordEncoder must be provided. PasswordEncoder is used to store end-user passwords in the database in an unreadable format. We should use any one implementation class object like:- BCryptPasswordEncoder(C), NoOpPasswordEncoder(C) [deprecated].
To avoid password encoding (Store password in plain text format) use NoOpPasswordEncoder.
To convert passwords we can use BCryptPasswordEncoder(C).
requestMatchers()
requestMatchers(path)
: This method is used to match(compare) request URL (path) with Controller#method URL (path). If they are matched then its connected authority type [permitAll()/authenticated()/hasRole()] is selected.
Examples:-
/register
can be accessed by everyone:-.requestMatchers("/register").permitAll()
/inbox
can be accessed by any user after login (any role is fine):-.requestMatchers("/inbox").authenticated()
/exportData
can be accessed by the user after login having a role – ADMIN:-.requestMatchers("/exportData").hasRole("ADMIN")
/import
can be accessed by the user after login having a role (any one of) – ADMIN/EMPLOYEE/STUDENT:-.requestMatchers("/import").hasAnyRole("ADMIN","EMPLOYEE","STUDENT")
/login
with HttpMethod GET can be accessed by everyone:-.requestMatchers(HttpMethod.GET, "/login").permitAll()
/save
with POST type can be accessed by any user after login:-.requestMatchers(HttpMethod.POST, "/save").authenticated()
anyRequest
()
anyRequest()
:- It indicates non-configure URLs that are in the Application (Controller paths) i.e. requestMatchers not provided URLs. Consider the example:- Project has 5 URLs at the Controller method level. URLs (paths): /show, /save, /export, /delete, /import. Anyone can access the/show and /export URLs without login. The /save URL can be accessed only by ADMIN only. The remaining URLS can be accessed only after login (any role). It can be configured as follows:-
.requestMatchers("/show").permitAll()
.requestMatchers("/export").permitAll()
.requestMatchers("/save").hasRole("ADMIN")
.anyRequest().authenticated()
It is good programming practice to write .anyRequest().authenticated()
at the end. So, in the future, we may add another endpoint to the application.
Types of Authentication
It specifies where to store user data. It is going to fetch data from the source given and compare it with login data (validate user login). There are 3 types of Authentication Manager:-
- InMemoryUserDetailsManager:- Store data in RAM and validate data/login when the request comes. It is used for testing purposes/ dev purposes.
- jdbcAuthentication:- Store data in the database and validate data/login when the request comes. It works based on SQL queries (given by the programmer).
- UserDetailsService:- It is used most commonly. It stores data in the database and validates data/login when the request comes. It works based on ORM (Spring Data JPA).
username | password | authorities |
---|---|---|
sam | sam | ADMIN |
syed | syed | EMPLOYEE |
william | william | STUDENT |
Using InMemoryUserDetailsManager it can be created as follows. Replace the UserDetailsService Bean configured in the SecurityConfig class as follows:-
@Bean
UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails admin = User.builder()
.username("sam")
.password(passwordEncoder.encode("sam"))
.roles("ADMIN")
.build();
UserDetails employee = User.builder()
.username("syed")
.password(passwordEncoder.encode("syed"))
.roles("EMPLOYEE")
.build();
UserDetails student = User.builder()
.username("william")
.password(passwordEncoder.encode("william"))
.roles("STUDENT")
.build();
return new InMemoryUserDetailsManager(admin, employee, student);
}
InMemoryUserDetailsManager Example
Create a project SecurityDemoSecurityInMemoryAuthDemo using the spring starter project with dependencies:- Spring Web, Spring Security (spring-boot-starter-security
), Thymeleaf, and Spring Boot Devtools (optional). We will use Thymeleaf to build some simple UI.
URL, UI, and its security configuration details.
URL | UI | Access Details |
---|---|---|
/home | HomePage.html | (permitAll) everyone can access |
/welcome | Welcome.html | (authenticated) only login users [No Role required] |
/admin | AdminPage.html | (hasAuthority[ADMIN) login + role-ADMIN |
/emp | EmployeePage.html | (hasAuthority[EMPLOYEE) login + role-EMPLOYEE |
/std | StudentPage.html | (hasAuthority[STUDENT) login + role-STUDENT |
/common | CommonPage.html | (hasAnyAuthority[ADMIN,EMPLOYEE) login + role-ADMIN/EMPLOYEE |
Remaining all URLs | N/A | (authenticated) only login users [No Role required] |
Project GitHub Link:- SecurityDemoSecurityInMemoryAuthDemo
Inside src/main/resources/templates folder:-
In HomePage.html
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Home Page</title>
</head>
<body>
<h1>Welcome to Home Page (No Security)</h1>
</body>
</html>
Similarly, create the following HTML pages (Just change the title and <h1> so we can identify the page easily):-
- WelcomePage.html
- AdminPage.html
- EmployeePage.html
- StudentPage.html
- CommonPage.html
In DeniedPage.html
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org/">
<head>
<meta charset="ISO-8859-1">
<title>Denied Page</title>
</head>
<body>
<h1>No Access Provided to You. Please Go to Welcome Page</h1>
<br/>
<a th:href="@{/welcome}">Home</a>
<a th:href="@{/logout}">Logout</a>
</body>
</html>
If the user doesn’t have access to a particular URL (due to Role) then instead of showing 403 HttpStatus code, we will route them to the DeniedPage.html.
Controller class:-
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/home")
public String showHome() {
return "HomePage";
}
@GetMapping("/welcome")
public String showWelcome() {
return "WelcomePage";
}
@GetMapping("/admin")
public String showAdmin() {
return "AdminPage";
}
@GetMapping("/emp")
public String showEmp() {
return "EmployeePage";
}
@GetMapping("/std")
public String showStudent() {
return "StudentPage";
}
@GetMapping("/common")
public String showCommon() {
return "CommonPage";
}
@GetMapping("/access-denied")
public String showDenied() {
return "DeniedPage";
}
}
Security Configuration:-
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails admin = User.builder()
.username("sam")
.password(passwordEncoder.encode("sam"))
.roles("ADMIN")
.build();
UserDetails employee = User.builder()
.username("syed")
.password(passwordEncoder.encode("syed"))
.roles("EMPLOYEE")
.build();
UserDetails student = User.builder()
.username("william")
.password(passwordEncoder.encode("william"))
.roles("STUDENT")
.build();
return new InMemoryUserDetailsManager(admin, employee, student);
}
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorizeRequests -> authorizeRequests
.requestMatchers("/home").permitAll()
.requestMatchers("/welcome").authenticated()
.requestMatchers("/admin").hasRole("ADMIN")
.requestMatchers("/emp").hasRole("EMPLOYEE")
.requestMatchers("/std").hasRole("STUDENT")
.requestMatchers("/common").hasAnyRole("ADMIN", "EMPLOYEE")
.anyRequest().authenticated()
)
// Login Form details
.formLogin(form -> form // default login form
.defaultSuccessUrl("/welcome", true)
.permitAll()
)
// Logout details
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll()
)
// Exception Details
.exceptionHandling(exception -> exception
// custom page to show access denied message
.accessDeniedPage("/access-denied")
);
return http.build();
}
}
Now try to access all URLs with different usernames/passwords. In Spring REST Security with JWT, we have used Spring Data JPA to store users in the database and JWT for token generation.
If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!