Welcome to Part 2 of my Build a blog series with Spring Boot and Angular.
In Part 1 , we created our project and basic domain entities and repositories. In this article, we will set up Spring Security and implement the API to register users in our application.
If you are a visual learner like me, you can have a look at the youtube video I have created as a companion to this post.
The source code of this project, is hosted on Github –https://github.com/SaiUpadhyayula/spring-ng-blog
https://github.com/SaiUpadhyayula/ng-spring-blog-frontend
What are we going to build in this part?
- First, we will see how to setup Spring Security in our application
- Then, we will build an API to register users in our application
- We will see how to encode the password of the user, before storing them in the database.
So let’s start coding.
Configure Spring Security
Let’s create the following class which holds the complete security configuration of our application, that’s why the class is named SecurityConfig.java
package com.programming.techie.springngblog.config;
import com.programming.techie.springngblog.security.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**")
.permitAll()
.anyRequest()
.authenticated();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Let’s understand what did we configure in the above class:
- @EnableWebSecurity
This is the main annotation which enables the Web Security module in our Project. - WebSecurityConfigurerAdapter
This is the base class for our SecurityConfig class, it provides us the default security configurations, which we can override in our SecurityConfig and customize them. - Configurations
Next, we have the configure method which we have overridden from the base class which takes HttpSecurity as an argument.
Here, we are configuring the Spring to allow all the requests which match the endpoint “/api/auth/**” , as these endpoints are used for authentication and registration we don’t expect the user to be authenticated at that point of time. - PasswordEncoder
Now before storing the user in the database, we ideally want to encode the passwords. One of the best hashing algorithms for passwords is the Bcrypt Algorithm. We are using the BCryptPasswordEncoder class provided by Spring Security. You can read more about this here
Now that is the minimumconfiguration we need to implement the Registration Functionality, in the upcoming blog posts, we will add more functionality to our SecurityConfig class as we implement the Login functionality using JWT. Let’s write the API for registering users.
Implement API to Register Users
So to register users, first of all, we need a Controller class, I will create it inside the following package: com.programming.techie.springngblog.controller. I will name our class file as AuthController.java
package com.programming.techie.springngblog.controller; import com.programming.techie.springngblog.dto.RegisterRequest; import com.programming.techie.springngblog.service.AuthService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/auth") public class AuthController { @Autowired private AuthService authService; @PostMapping("/signup") public ResponseEntity signup(@RequestBody RegisterRequest registerRequest) { authService.signup(registerRequest); return new ResponseEntity(HttpStatus.OK); } }
So we have created a RestController and inside this controller, we have first created a method that will be invoked whenever a POST request is made to register the user’s in our application.
The API call should contain the request body which is of type RegisterRequest. We call this kind of classes as a DTO (Data Transfer Object). We will create this class inside a different package called com.programming.techie.springngblog.dto
RegisterRequest.java
package com.programming.techie.springngblog.dto;
public class RegisterRequest {
private String username;
private String email;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
This signup method is calling another method inside the AuthService class, which is mainly responsible to create the User object and storing it in the database. Now let’s create this AuthService class inside the com.programming.techie.springngblog.service.
AuthService.java
package com.programming.techie.springngblog.service;
import com.programming.techie.springngblog.dto.RegisterRequest;
import com.programming.techie.springngblog.model.User;
import com.programming.techie.springngblog.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class AuthService {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
public void signup(RegisterRequest registerRequest) {
User user = new User();
user.setUserName(registerRequest.getUsername());
user.setEmail(registerRequest.getEmail());
user.setPassword(encodePassword(registerRequest.getPassword()));
userRepository.save(user);
}
private String encodePassword(String password) {
return passwordEncoder.encode(password);
}
}
Inside the AuthService class, we are mapping the RegisterRequest object to the User object and when setting the password, we are calling the encodePassword method. This method is using the BCryptPasswordEncoder to encode our password. After that, we save the user into the database.
Lets Review the Project Structure
We have created some classes and packages, the project structure should look something like below:
Let’s Test the API
Now its time to test the API we have created, start the application by typing below command in the terminal
mvn spring-boot:run
and make a POST request to our Signup API using POSTMAN, which looks like below:
You can see that we received a 200 OK response back from the server, which means the User is saved successfully in the database.
So you can see that our User is successfully saved in the database, the password is not in a human-readable format, it is encoded using the BCrypt algorithm.
What’s next?
So this concludes this post, in the next article, we will see how to implement Login API and how to configure JWT in our application.