Login/Registration Example with Spring Boot

Devquora
7 min readJan 29, 2019

--

Spring Boot Interview Questions For Freshers & Experienced

Creating a Login Registration Application in Spring Boot. Spring Boot is a module of spring framework that provides Rapid Application Development. It allows you to create stand-alone, production-grade Spring based Applications that you can “just run”. In this tutorial, I am going to create simple Registration and Login functionality with Spring Boot, Spring Security, Spring Data JPA, and HSQL. Let’s move step by step.

Suggested Read: What is Spring Boot

Prerequisites

  • JDK 1.7 or later
  • Maven 3 or later

Stacks Used in Project

  • Spring Security
  • Spring Boot
  • Spring Data
  • JPA
  • JSP

Project Structure

├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── springbootapp
│ │ └── auth
│ │ ├── model
│ │ │ ├── Role.java
│ │ │ └── User.java
│ │ ├── repository
│ │ │ ├── RoleRepository.java
│ │ │ └── UserRepository.java
│ │ ├── service
│ │ │ ├── SecurityServiceImpl.java
│ │ │ ├── SecurityService.java
│ │ │ ├── UserDetailsServiceImpl.java
│ │ │ ├── UserServiceImpl.java
│ │ │ └── UserService.java
│ │ ├── validator
│ │ │ └── UserValidator.java
│ │ ├── web
│ │ │ └── UserController.java
│ │ ├── WebApplication.java
│ │ └── WebSecurityConfig.java
│ ├── resources
│ │ ├── application.properties
│ │ └── validation.properties
│ └── webapp
│ ├── resources
│ │ ├── css
│ │ │ ├── bootstrap.min.css
│ │ │ └── common.css
│ │ └── js
│ │ └── bootstrap.min.js
│ ├── login.jsp
│ ├── registration.jsp
│ └── welcome.jsp
└── pom.xml

Dependencies of Project 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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>auth</artifactId>
<name>auth</name>
<description>auth</description>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Defining JPA Entities

In spring you can define JPA Entity with @Entity annotation, which represents a table in your database.

Creating our User Model

Create a new file named User.java in src/main/java/com/springbootapp/auth/model/ directory and add following lines of code.

package com.springbootapp.auth.model;import javax.persistence.*;
import java.util.Set;
@Entity
@Table(name = "user")
public class User {
private Long id;
private String username;
private String password;
private String passwordConfirm;
private Set roles;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Transient
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
@ManyToMany
@JoinTable(name = "user_role",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
}
Best Interview Questions and answers on Spring Boot
Spring Boot Interview Questions

Create another file named Role.java in src/main/java/com/springbootapp/auth/model/

package com.springbootapp.auth.model;import javax.persistence.*;
import java.util.Set;
@Entity
@Table(name = "role")
public class Role {
private Long id;
private String name;
private Set users;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany(mappedBy = "roles")
public Set getUsers() {
return users;
}
public void setUsers(Set users) {
this.users = users;
}
}

Working with Spring Data JPA Repositories

This contains some pre-built Repository implemented to perform common tasks with the database like finding, saving, updating records. records: findOne, findAll, save.

Create a new file named UserRepository.java in src/main/java/com/springbootapp/auth/repository/ add following code in it.

package com.springbootapp.auth.repository;import com.springbootapp.auth.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository {
User findByUsername(String username);
}

Create another file RoleRepository.java in src/main/java/com/springbootapp/auth/repository/ and add follwing line on code.

package com.springbootapp.auth.repository;import com.springbootapp.auth.model.Role;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleRepository extends JpaRepository{
}

Implementing Spring Security’s

To implement login/authentication with Spring Security, we need to implement org.springframework.security.core.userdetails.UserDetailsService interface,so create an new file named UserDetailsServiceImpl.java in src/main/java/com/springbootapp/auth/service/ directory add following code in it.

Suggested Read: spring boot tricky interview questions

package com.springbootapp.auth.service;import com.springbootapp.auth.model.Role;
import com.springbootapp.auth.model.User;
import com.springbootapp.auth.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashSet;
import java.util.Set;
@Service
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private UserRepository userRepository;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
Set grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()){
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(),
user.getPassword(), grantedAuthorities);
}
}

Security Service

Next, We are going to create SecurityService that provides functionality to current logged in user and auto login user after registering an account.

Create a new file SecurityServiceImpl.java in src/main/java/com/springbootapp/auth/service/ directory and add the follwing line of code

package com.springbootapp.auth.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
@Service
public class SecurityServiceImpl implements SecurityService{
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
private static final Logger logger = LoggerFactory.getLogger
(SecurityServiceImpl.class);
@Override
public String findLoggedInUsername() {
Object userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
if (userDetails instanceof UserDetails) {
return ((UserDetails)userDetails).getUsername();
}
return null;
}
@Override
public void autologin(String username, String password) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
= new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
authenticationManager.authenticate(usernamePasswordAuthenticationToken);if (usernamePasswordAuthenticationToken.isAuthenticated()) {
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
logger.debug(String.format("Auto login %s successfully!", username));
}
}
}

User Service

Create a new file UserServiceImpl.java in src/main/java/com/springbootapp/auth/service/ directory. This file provides service service for registering an account.

package com.springbootapp.auth.service;import com.springbootapp.auth.model.User;
import com.springbootapp.auth.repository.RoleRepository;
import com.springbootapp.auth.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.HashSet;@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Override
public void save(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
user.setRoles(new HashSet<>(roleRepository.findAll()));
userRepository.save(user);
}
@Override
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
}

Adding Spring validator

Implement org.springframework.validation.Validator to provide validation to our registration controller.

Create a file name UserValidator.java in src/main/java/com/springbootapp/auth/validator/ directory and add following code.

package com.springbootapp.auth.validator;import com.springbootapp.auth.model.User;
import com.springbootapp.auth.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
@Component
public class UserValidator implements Validator {
@Autowired
private UserService userService;
@Override
public boolean supports(Class aClass) {
return User.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors) {
User user = (User) o;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "NotEmpty");
if (user.getUsername().length() < 6 || user.getUsername().length() > 32) {
errors.rejectValue("username", "Size.userForm.username");
}
if (userService.findByUsername(user.getUsername()) != null) {
errors.rejectValue("username", "Duplicate.userForm.username");
}
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "NotEmpty");
if (user.getPassword().length() < 8 || user.getPassword().length() > 32) {
errors.rejectValue("password", "Size.userForm.password");
}
if (!user.getPasswordConfirm().equals(user.getPassword())) {
errors.rejectValue("passwordConfirm", "Diff.userForm.passwordConfirm");
}
}
}

Creating our controller for login and registration.

This controller is responsible for authenticating/ registering users. Create a new file UserController.java in src/main/java/com/springbootapp/auth/web/ and add follwing code.

package com.springbootapp.auth.web;import com.springbootapp.auth.model.User;
import com.springbootapp.auth.service.SecurityService;
import com.springbootapp.auth.service.UserService;
import com.springbootapp.auth.validator.UserValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class UserController {
@Autowired
private UserService userService;
@Autowired
private SecurityService securityService;
@Autowired
private UserValidator userValidator;
@RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(Model model) {
model.addAttribute("userForm", new User());
return "registration";
}
@RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(@ModelAttribute("userForm") User userForm,
BindingResult bindingResult, Model model) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "registration";
}
userService.save(userForm);securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());return "redirect:/welcome";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("error", "Your username and password is invalid.");
if (logout != null)
model.addAttribute("message", "You have been logged out successfully.");
return "login";
}
@RequestMapping(value = {"/", "/welcome"}, method = RequestMethod.GET)
public String welcome(Model model) {
return "welcome";
}
}

Managing our Application Properties

Add following code in src/main/resources/application.properties file

spring.mvc.view.prefix: /
spring.mvc.view.suffix: .jsp
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.messages.basename=validation

Add following code in src/main/resources/validation.properties file

NotEmpty=This field is required.
Size.userForm.username=Please use between 6 and 32 characters.
Duplicate.userForm.username=Someone already has that username.
Size.userForm.password=Try one with at least 8 characters.
Diff.userForm.passwordConfirm=These passwords don't match.

Managing Web Security Configuration

Add following lines of code in src/main/java/com/springbootapp/auth/WebSecurityConfig.java

package com.springbootapp.auth;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}

Application Configuration

Add following lines of code in src/main/java/com/springbootapp/auth/WebApplication.java

package com.springbootapp.auth;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
@SpringBootApplication
public class WebApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplircationBuilder application) {
return application.sources(WebApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(WebApplication.class, args);
}
}

Running the applications

Run the application using maven clean spring-boot: run and visit to http://localhost:8080

Conclusion

After reading this article you are now able to create a simple login and registration application in Spring Boot.

References

https://hellokoding.com/registration-and-login-example-with-spring-security-spring-boot-spring-data-jpa-hsql-jsp/

https://www.youtube.com/watch?v=7Vp6iXmO30E

--

--

Devquora

Devquora is an online network of developers basically a (Developer 2 developer Network) for solving problems day to day common code problems of developer