Last Updated on 14 March 2024   |   Print Email
In this tutorial, you will learn to secure webpages in a Spring Boot application using Spring Security APIs. The authentication method to be used is HTTP Basic with credentials are user details stored in memory. In other words, how to quickly add simple login function for a Java web application based on Spring framework, without creating login form.Using HTTP Basic authentication with in-memory users is suitable for applications that require only simple security which can be implemented quickly.The Spring security code in this tutorial is built on top of the codebase of the project described in the tutorial: Spring Boot CRUD Example with Spring Data JPA. So to follow this tutorial, go to download the sample project that tutorial.NOTE: The code examples in this post have been updated to Spring Boot 3.x, Spring Security 6.x, and Thymeleaf 3.1.2.
1. Understand HTTP Basic Authentication
Let’s understand some key characteristics of HTTP basic authentication. It is one of the standard authentication mechanisms defined by HTTP specification. The web browser provides a login dialog box that requires the users to enter username and password, which is sent to the server via HTTP headers. No cookies or sessions are used.In HTTP basic authentication, the credentials are weakly encoded using Base64 encoding algorithm which is easily reversible. That means this method is not secured, unless used in conjunction with HTTPS.And note that, there’s no explicit logout with HTTP basic authentication. To force logout, you must exit the browser.
2. Declare Spring Security Dependency
To use Spring Security APIs, add the following dependency declaration in the project’s Maven build file:
If Spring Security jar files are present in the classpath, the default authentication method is form-based with a prebuilt login form provided. But we will be using HTTP Basic authentication instead.
3. Configure HTTP Basic Authentication with in-memory users
Now, we want to secure all pages of the ProjectManager application (download here). Create the WebSecurityConfig class with the following code:
Note that this class must be annotated with the @EnableWebSecurity annotation and overrides a couple of configure() methods from its superclass WebSecurityConfigurerAdapter.The first method is to create in-memory users:
Here, we create two users namhm and admin with passwords encoded in BCrypt format because raw passwords are not recommended. BCrypt is a strong hashing algorithm recommended by Spring Security.You can create a simple program to generate BCrypt password as follows:
package net.codejava;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class SecuredPasswordGenerator {
public static void main(String[] args) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String rawPassword = "nimda";
String encodedPassword = encoder.encode(rawPassword);
System.out.println(encodedPassword);
}
}
With this configuration, all requests must be authenticated using HTTP basic authentication method. NOTE: If you're using Spring Boot 3.x with Spring Security 6.x, update the WebSecurityConfig class as follows:
Open the web browser to access the application at http://localhost:8080, you will see the browser presents a login dialog box that looks like this:This dialog may look slightly different in different browsers. Enter username is namhm and password is codejava, and click Sign in. Once authenticated successfully, the home page appears:You can see, it displays “Welcome namhm” – username of the logged in user.To logout, you must exit the browser.
5. Bonus: Code Authorization
Let’s go further beyond basic authentication. Now we want to authorize users based on their roles, and every one can see the home page (not secured). Only users having ADMIN role can edit and delete products, and users having either USER or ADMIN role can create new product.So update the second method in the WebSecurityConfig class as follows:
Here, we also specify a custom error page for the HTTP status 403 – in case the user is not authorized. Code of this custom error page may be as simple as follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Access Denied</title>
</head>
<body>
<h2>Sorry, you don't have permission!</h2>
</body>
</html>
Of course you need to configure Spring MVC view resolver accordingly so the /403 URL will be resolved to the HTML file 403.html. NOTE: If Spring Boot 3.x with Spring Security 6.x are used, update the web security configuration class as follows:
You may want to have more granularity for authorization, such as only users having ADMIN role can see Edit and Delete links. So you need to use Thymeleaf integration with Spring Security.Declare the following dependency for the project:
This means only users having USER role can see welcome message. And only users having either USER or ADMIN role can see the Create New Product link:
<div sec:authorize="hasAnyRole('USER', 'ADMIN')">
<a href="/new">Create New Product</a>
</div>
Conclusion:So that you have learned how to secure a Spring Boot application using HTTP basic authentication method with in-memory users. You also learned how to implement simple role-based authorization. You see, Spring framework makes it very easy to secure Java web applications. And you can download the sample project in the Attachments section below, or clone the sample code on GitHub.You can also watch the video version of this tutorial here:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.
Hi Jose. Sure you can. For example: @Bean public UserDetailsService userDetailsService() throws Exception { Properties users = PropertiesLoaderUtils.loadAllProperties("users.properties"); return new InMemoryUserDetailsManager(users); }
Comments
Sure you can. For example:
@Bean
public UserDetailsService userDetailsService() throws Exception {
Properties users = PropertiesLoaderUtils.loadAllProperties("users.properties");
return new InMemoryUserDetailsManager(users);
}
I love your site, you are a good person!
Thanks again.