Back to: Spring Boot Tutorials
Spring Boot Security with Examples
In this article, I am going to discuss Spring Boot Security with Examples. Please read our previous article where we discussed Spring Boot HTTP Header Versioning with Examples.
What is Spring Security?
We have learned how to create several REST APIs so far. None of these APIs are secure as no authentication is performed before the data is sent to the client. In this exercise, we will implement basic authentication.
Spring Boot offers multiple authentication methods. The most convenient method is basic authentication. With this method, the client sends a username and password as part of the request. If the username and password combination is correct, the client is granted access to the data.
There are also more advanced forms of authentication, such as digest authentication, where a password digest is created and sent instead of the actual password. Another advanced form of authentication is OAuth (Open Authorization) or OAuth2 authentication.
Implementing Authentication in Spring Boot
Let’s now learn how to implement basic authentication in web services. For this project, we shall again use the fruits API. The project should have the following class files:
- Fruits.java
- FruitServiceController.java
- SecurityApplication.java
The contents of these files need not be modified in this project. The code in these files is provided at the end of this webpage.
As of now, the application does not have any form of authentication. We will have to implement this using Spring Security.
Step 1: Add the Spring Security dependency to the project using the “Add Starters…” option. This option is available in the right-click menu of the pom.xml file.
Ensure that the dependency has been installed:
Step 2: Compile and execute the application. Ensure compilation is successful.
As can be seen from the terminal output, a password is generated for authentication. Note that this password shall change every time the application is restarted.
Step 3: Send a GET request to the URL http://localhost:8080/products via Postman. You should see the following error:
This error occurs because we have not entered a user id and password.
Step 4: Send a GET request to the URL http://localhost:8080/products via Postman. Remember to enter the userid and password using the authorization tab in Postman. Copy the password correctly from the Spring Boot terminal window. You should see the following reply:
As can be seen, this returns the expected output. If we enter the incorrect password, the following error will be displayed:
Step 5: Until now, we have been using the password automatically created by Spring Boot. A better option would be to configure the user id and password ourselves. This can be done by modifying the application.properties file.
Step 6: Compile and execute the application. Ensure compilation is successful.
As can be seen from the terminal output, Spring Boot does not generate a new password for us to use.
Step 7: Send a GET request to the URL http://localhost:8080/products via Postman. Remember to enter the userid and password using the authorization tab in Postman. Enter the password as you have done in the application.properties file.
Congratulations! You now know how to implement authorization in Spring Boot. Note that this is just basic authentication, which can be breached easily. Other forms of authentication, such as OAuth and OAuth2 provide a much more secure authorization mechanism.
The Complete Example Code
Fruits.java
package com.dotnet.security; public class Fruits { private String id; private String name; public String getId() {return id;} public void setId(String id) {this.id = id;} public String getName() {return name;} public void setName(String name) {this.name = name;} public Fruits (String nid, String nname) { id = nid; name = nname; } }
FruitServiceController.java
package com.dotnet.security; //Map classes import java.util.HashMap; import java.util.Map; //Required web classes import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class FruitServiceController { private static Map<String, Fruits> productRepo = new HashMap<>(); static { Fruits apple = new Fruits("1","Apple"); productRepo.put(apple.getId(), apple); Fruits banana = new Fruits("2","Banana"); productRepo.put(banana.getId(), banana); Fruits chiku = new Fruits("3","Chiku"); productRepo.put(chiku.getId(), chiku); Fruits dragon = new Fruits("4","Dragon Fruit"); productRepo.put(dragon.getId(), dragon); } @RequestMapping(value = "/products/{id}", method = RequestMethod.DELETE) public ResponseEntity<Object> delete(@PathVariable("id") String id) { productRepo.remove(id); return new ResponseEntity<>("Fruit is deleted!", HttpStatus.OK); } @RequestMapping(value = "/products/{id}", method = RequestMethod.PUT) public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody Fruits product) { productRepo.remove(id); product.setId(id); productRepo.put(id, product); return new ResponseEntity<>("Fruit is updated!", HttpStatus.OK); } @RequestMapping(value = "/products", method = RequestMethod.POST) public ResponseEntity<Object> createProduct(@RequestBody Fruits product) { productRepo.put(product.getId(), product); return new ResponseEntity<>("Fruit is created!", HttpStatus.CREATED); } @RequestMapping(value = "/products") public ResponseEntity<Object> getProduct() { return new ResponseEntity<>(productRepo.values(), HttpStatus.OK); } }
SecurityApplication.java
package com.dotnet.security; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SecurityApplication { public static void main(String[] args) { SpringApplication.run(SecurityApplication.class, args); } }
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.dotnet</groupId> <artifactId>security</artifactId> <version>0.0.1-SNAPSHOT</version> <name>security</name> <description>Demo project for Spring Boot</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.properties
spring.security.user.name=user spring.security.user.password=secure_pass
In the next article, I am going to discuss Richardson Maturity Model with Examples. Here, in this article, I try to explain Spring Boot Security with Examples. I hope you enjoy this Spring Boot Security article.