- • Quickstart
- • Documentation
- • Documentation DevOps
- • Next Steps
- • Spring Boot
- • Spring Data
- • Spring Data MongoDB
- › Spring Security
- • Frontend
- • Multi-Module
Last updated: 2023-11-24
Form Login with Spring Boot and Thymeleaf
The form-based login is often the first choice to protect the web frontend of a Spring Boot application. It ensures that certain areas of our application are only accessible once a user has authenticated himself with a username and password, and this status is stored in the session. What are the steps required to add form based login to our Spring Boot application?
Start with a simple application
First, we use the Bootify Builder to create a simple Spring Boot application in the current version
3.2.3 - to do this, we simply click on start project. There we select
Thymeleaf + Bootstrap as frontend stack - Thymeleaf is the most used template engine of Spring Boot and allows server-side rendering. Bootstrap will be integrated into our app as a WebJar. Select any database which you would like to connect to - an embedded database will do for now as well.
In the Entities Tab we create the tables
User as well as
TodoList, and connect them with an
N:1 relation. For the TodoList we activate the CRUD option for the frontend - this will be the area we secure with Spring Security afterwards.
Preview of our very simple database schema
Now we can already download the finished application and import it into our favorite IDE.
The first version of our application in IntelliJ
Configuration of Spring Security
The form-based login is provided with the help of Spring Security. So we first need the relevant dependencies, which we add to our
spring-boot-starter-security integrates Spring Security. With
thymeleaf-extras-springsecurity6 a little helper is included which provides the authentication state in our Thymeleaf templates - more about that later.
With this we can already provide the central security configuration - here directly in our final version.
Our configuration for the form login
Theoretically, Spring Security can provide the login form with less configuration, but this would lack the design and some messages which we would like to present to the user. But let's go through the config first.
BCryptPasswordEncoder is standard nowadays to store the hash of a password together with its individual salt inside a single field. If we don't have a legacy requirement, we should use this one. Also, we provide the
AuthenticationManager as a bean to be able to integrate it into other services.
As a third bean we create the
SecurityFilterChain as this is the required approach since Spring 3.0. We should configure both CORS and CSRF properly to close the corresponding attack vectors. The default configuration is usually sufficient for this.
At our config class we have placed the annotation
@EnableMethodSecurity and will protect the desired controller endpoints with
@PreAuthorize(...) later on. Therefore we allow access to the whole application with
permitAll(). Without the annotation based security, we should configure the paths to the protected resources at this place as well.
formLogin() and the
logout() methods are customized for our subsequent controller so that we can always display an appropriate message to the user. Spring Security automatically provides an endpoint for the login where username and password can be submitted to via POST request. Here we change the name of the username field to
"email". The logout is modified to redirect back to the login page with a parameter afterwards.
Loading users from our database
To load the users from the already created table, we need to provide an implementation of
UserDetailsService as a bean - it will be automatically found and used as a user source.
UserDetailsService implementation automatically used as the user source
In our repository we should add a method
User findByEmailIgnoreCase(String email) to execute a search query against the database - ignoring upper/lower case allows the user small mistakes when writing their email. The role here is always
ROLE_USER for each user. Since we don't have a registration endpoint available at this point, we can add a simple data loader along with our application for now. The profile
"local" is required for it to become active.
Helper class to initialize a first user locally
Add login controller
With this we can already add the
LoginController. Since the POST endpoint is automatically provided by Spring Security, a GET endpoint is sufficient here to show the template to the user.
Backend for rendering the login page
The request parameters that we had already specified in our security configuration are converted to corresponding messages here. In our simple application from Bootify the corresponding helpers are already included. Here we also need the
AuthenticationRequest object with getters and setters.
The corresponding template for our controller could then look like this.
As Thymeleaf doesn't allow direct access to request object anymore, we're providing the
requestUri in the model.
Providing the requestUri - as part of the AuthenticationController or a general ControllerAdvice
With this template we send a POST request to the
/login endpoint. The INFO or ERROR messages are automatically displayed by the layout. All used messages have to be present in our
Last we can extend our
layout.html. With this we also always show a login / logout link in the header. Spring Security also automatically provides a
/logout endpoint, but we have to address it via POST.
Adding login / logout links to our layout
html tag we've extended the namespace to use the helpers from the
thymeleaf-extras-springsecurity6 module. As a final step we only need to add the annotation
@PreAuthorize("hasAuthority('ROLE_USER')") at our
Starting our application
With this we have all needed pieces of our puzzle together! Now we start our application and when we want to see the todo lists, we should be redirected to the login page. Here we can log in with
[email protected] /
Automatic redirect to the login
In the Free plan of Bootify, Spring Boot prototypes with its own database schema, REST API and frontend can be generated. In the Professional plan, among other things, Spring Security with the form-based login is available to generate the setup described here - exactly matching the created database and the selected settings. A registration endpoint and role source can be specified as well.