This guide provides instructions on how to add Spring Security to an existing Spring Boot application.
Setting up the sample
This section outlines how to setup a workspace within Spring Tool Suite (STS) so that you can follow along with this guide. The next section outlines generic steps for how to apply Spring Security to your existing application. While you could simply apply the steps to your existing application, we encourage you to follow along with this guide in order to reduce the complexity.
Obtaining the sample project
Extract the Spring Security Distribution to a known location and remember it as SPRING_SECURITY_HOME.
Import the insecure sample application
In order to follow along, we encourage you to import the insecure sample application into your IDE. You may use any IDE you prefer, but the instructions in this guide will assume you are using Spring Tool Suite (STS).
The completed sample application can be found at SPRING_SECURITY_HOME/samples/boot/helloworld |
-
If you do not have STS installed, download STS from https://spring.io/tools
-
Start STS and import the sample application into STS using the following steps:
-
File→Import
-
Existing Maven Projects
-
Click Next >
-
Click Browse…
-
Navigate to the samples (i.e. SPRING_SECURITY_HOME/samples/boot/insecure) and click OK
-
Click Finish
-
Running the insecure application
In the following exercise we will be modifying the spring-security-samples-boot-insecure application. Before we make any changes, it is best to verify that the sample works properly. Perform the following steps to ensure that spring-security-samples-boot-insecure works.
-
Right click on the spring-security-samples-boot-insecure application
-
Select Run As→Spring Boot App
Verify the application is working by navigating to http://localhost:8080/
Click on the secured pages link and verify the page states TODO Secure this
Once you have verified the application runs, stop the application server using the following steps:
-
In the Boot Dashboard view select the running application
-
Click the stop button (a red square) to stop the application
Securing the application
Before securing the application, it is important to ensure that the existing application works as we did in Running the insecure application. Now that the application runs without security, we are ready to add security to our application. This section demonstrates the minimal steps to add Spring Security to our application.
Updating your dependencies
In order to resolve Spring Security milestones and release candidates add the Spring Milestone repository. For our example, the repository has already been added for you. In the event you were working on another application, you would need to ensure you add the following to your pom:
<repositories>
<!-- ... possibly other repository elements ... -->
<repository>
<id>spring-milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
In order to use Spring Security you must add the necessary dependencies. For the sample we will add the following Spring Security dependencies:
<dependencies>
<!-- ... other dependency elements ... -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId> (1)
<version>2.1.2.RELEASE</version>
</dependency>
</dependencies>
1 | We are using Thymeleaf for our view template engine and need to add an additional dependency for the Thymeleaf - Spring Security integration module. |
After you have completed this, you need to ensure that STS knows about the updated dependencies by:
-
Right click on the spring-security-samples-boot-insecure application
-
Select Maven→Update project…
-
Ensure the project is selected, and click OK
Creating your Spring Security configuration
The next step is to create a Spring Security configuration.
-
Right click the spring-security-samples-boot-insecure project in the Package Explorer view
-
Select New→Class
-
Enter org.springframework.security.samples.config for the Package
-
Enter SecurityConfig for the Name
-
Click Finish
-
Replace the file with the following contents:
package org.springframework.security.samples.config;
import org.springframework.beans.factory.annotation.Autowired;
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;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**", "/index").permitAll() (1)
.antMatchers("/user/**").hasRole("USER") (2)
.and()
.formLogin()
.loginPage("/login").failureUrl("/login-error"); (3)
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
1 | requests matched against /css/** and /index are fully accessible |
2 | requests matched against /user/** require a user to be authenticated and must be associated to the USER role |
3 | form-based authentication is enabled with a custom login page and failure url |
The name of the configureGlobal method is not important. However, it is important to only configure AuthenticationManagerBuilder in a class annotated with either @EnableWebSecurity , @EnableGlobalMethodSecurity , or @EnableGlobalAuthentication . Doing otherwise has unpredictable results.
|
The SecurityConfig will:
-
Require authentication to requests matched against /user/**
-
Specifies the URL to send users to for form-based login
-
Allow the user with the Username user and the Password password to authenticate with form based authentication
-
Allow the user to logout
-
CSRF attack prevention
-
Session Fixation protection
-
Security Header integration
-
HTTP Strict Transport Security for secure requests
-
X-Content-Type-Options integration
-
Cache Control (can be overridden later by your application to allow caching of your static resources)
-
X-XSS-Protection integration
-
X-Frame-Options integration to help prevent Clickjacking
-
-
Integrate with the following Servlet API methods
Exploring the secured application
Start the application as we did in Running the insecure application
Navigate to http://localhost:8080/ and click on the secured pages link and you will be prompted to login.
Authenticating to the secured application
Try entering an invalid username and password:
-
Username invalid
-
Password invalid
You should see an error message stating that authentication failed. Now try entering a valid username and password:
-
Username user
-
Password password
You should now see the page that we wanted to secure.
The reason we can successfully authenticate with Username user and Password password is because that is what we configured in our SecurityConfig. |
Displaying the user name
Now that we have authenticated, let’s update the application to display the username. Update the complete content of /index.html with the following:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<title>Hello Spring Security</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div th:fragment="logout" class="logout" sec:authorize="isAuthenticated()"> (1)
Logged in user: <span sec:authentication="name"></span> | (2)
Roles: <span sec:authentication="principal.authorities"></span> (3)
<div>
<form action="#" th:action="@{/logout}" method="post"> (4)
<input type="submit" value="Logout" />
</form>
</div>
</div>
<h1>Hello Spring Security</h1>
<p>This is an unsecured page, but you can access the secured pages after authenticating.</p>
<ul>
<li>Go to the <a href="/user/index" th:href="@{/user/index}">secured pages</a></li>
</ul>
</body>
</html>
We are using Thymeleaf for our view template engine and Thymeleaf - Spring Security integration modules in order to utilize the sec:authentication and sec:authorize attributes. |
1 | Displays the Thymeleaf fragment (DOM Node) if the current user has been authenticated. |
2 | Displays the name of the currently authenticated principal. |
3 | Displays the authorities of the currently authenticated principal. |
4 | The logout form. |
Thymeleaf will automatically add the CSRF token to our logout form. If we were not using Thymleaf or Spring MVCs taglib we could also manually add the CSRF token using <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> .
|
Update the secured page
The last step is to update the secured page to also display the currently authenticated principal. Update the complete content of /user/index.html with the following:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello Spring Security</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div th:substituteby="index::logout"></div>
<h1>This is a secured page!</h1>
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
</body>
</html>
Start up the server and try visiting http://localhost:8080/ to see the updates to our application.
Conclusion
You should now know how to secure your application using Spring Security with an existing Spring Boot application . To learn more refer to the Spring Security Guides index page.