Spring Boot Vue.js User Registration and Login Example Tutorial

In this tutorial, we will create a full-stack application using Spring Boot 3 for the backend and Vue.js 3.4 for the frontend. We will implement user registration and login functionalities. The tutorial will cover setting up the project, creating the backend with Spring Boot, Spring Security for user registration and login functionalities, and building the frontend with Vue.js.

Prerequisites

Before we start, ensure you have the following:

  • Java Development Kit (JDK) installed
  • Apache Maven installed
  • Node.js and npm installed
  • An IDE (such as IntelliJ IDEA, Eclipse, or VS Code) installed

Step 1: Setting Up the Spring Boot Project

1.1 Create a Spring Boot Project

  1. Open Spring Initializr:

  2. Configure Project Metadata:

    • Project: Maven Project
    • Language: Java
    • Spring Boot: Select the latest version of Spring Boot 3
    • Group: com.example
    • Artifact: user-registration
    • Name: user-registration
    • Description: User Registration and Login Application with Spring Boot and Vue.js
    • Package Name: com.example.userregistration
    • Packaging: Jar
    • Java Version: 17 (or your preferred version)
    • Click Next.
  3. Select Dependencies:

    • On the Dependencies screen, select the dependencies you need:
      • Spring Web
      • Spring Data JPA
      • H2 Database
      • Spring Boot DevTools
      • Spring Security
    • Click Next.
  4. Generate the Project:

    • Click Generate to download the project zip file.
    • Extract the zip file to your desired location.
  5. Open the Project in Your IDE:

    • Open your IDE and import the project as a Maven project.

1.2 Update application.properties

Open the application.properties file located in the src/main/resources directory and add the following configuration:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update

1.3 Create the User Entity

In the com.example.userregistration.model package, create a new Java class named User:

package com.example.userregistration.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    private String email;
    private String password;

    // Getters and Setters
}

1.4 Create the UserRepository Interface

In the com.example.userregistration.repository package, create a new Java interface named UserRepository:

package com.example.userregistration.repository;

import com.example.userregistration.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    User findByEmail(String email);
}

1.5 Create the UserService Class

In the com.example.userregistration.service package, create a new Java class named UserService:

package com.example.userregistration.service;

import com.example.userregistration.model.User;
import com.example.userregistration.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Collections;

@Service
public class UserService implements UserDetailsService {

    private final UserRepository userRepository;
    private final BCryptPasswordEncoder passwordEncoder;

    @Autowired
    public UserService(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    public User saveUser(User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return userRepository.save(user);
    }

    public User findByEmail(String email) {
        return userRepository.findByEmail(email);
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found");
        }
        return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), Collections.emptyList());
    }
}

1.6 Create the AuthController Class

In the com.example.userregistration.controller package, create a new Java class named AuthController:

package com.example.userregistration.controller;

import com.example.userregistration.model.User;
import com.example.userregistration.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class AuthController {

    private final UserService userService;
    private final AuthenticationManager authenticationManager;

    @Autowired
    public AuthController(UserService userService, AuthenticationManager authenticationManager) {
        this.userService = userService;
        this.authenticationManager = authenticationManager;
    }

    @PostMapping("/register")
    public User registerUser(@RequestBody User user) {
        return userService.saveUser(user);
    }

    @PostMapping("/login")
    public String loginUser(@RequestBody User user) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword())
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return "User logged in successfully";
    }
}

1.7 Configure Spring Security

Create a new Java class named SecurityConfig in the com.example.userregistration.config package:

package com.example.userregistration.config;

import com.example.userregistration.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final UserService userService;

    @Autowired
    public SecurityConfig(UserService userService) {
        this.userService = userService;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/auth/**").permitAll()
                .anyRequest().authenticated()
            );

        return http.build();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}

Step 2: Creating the Frontend with Vue.js

2.1 Set Up Vue Project

  1. Open a terminal and navigate to your workspace directory.

  2. Create a new Vue project using Vue CLI:

    npm install -g @vue/cli
    vue create vue-frontend
    
  3. Navigate to the project directory:

    cd vue-frontend
    

2.2 Install Axios and Bootstrap

Install Axios to make HTTP requests and Bootstrap for styling:

npm install axios bootstrap

2.3 Create Components

Create the necessary components for user registration and login.

2.3.1 Create AuthService.js

Create a new file AuthService.js in the src directory to handle API requests for authentication:

import axios from 'axios';

const API_BASE_URL = "http://localhost:8080/auth";

class AuthService {
    register(user) {
        return axios.post(`${API_BASE_URL}/register`, user);
    }

    login(user) {
        return axios.post(`${API_BASE_URL}/login`, user);
    }
}

export default new AuthService();

2.3.2 Create RegisterComponent.vue

Create a new file RegisterComponent.vue in the src/components directory:

<template>
  <div class="container mt-5">
    <div class="row justify-content-center">
      <div class="col-md-6">
        <div class="card">
          <div class="card-header">Registration</div>
          <div class="card-body">
            <form @submit.prevent="registerUser">
              <div class="form-group">
                <label>First Name</label>
                <input v-model="user.firstName" class="form-control" type="text" placeholder="Enter first name" />
              </div>
              <div class="form-group">
                <label>Last Name</label>
                <input v-model="user.lastName" class="form-control" type="text" placeholder="Enter last name" />
              </div>
              <div class="form-group">
                <label>Email</label>
                <input v-model="user.email" class="form-control" type="email" placeholder="Enter email address" />
              </div>
              <div class="form-group">
                <label>Password</label>
                <input v-model="user.password" class="form-control" type="password" placeholder="Enter password" />
              </div>
              <button type="submit" class="btn btn-primary">Register</button>
            </form>
            <div class="mt-3">
              <span>Already registered? <router-link to="/login">Login here</router-link></span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import AuthService from '../AuthService';

export default {
  data() {
    return {
      user: {
        firstName: '',
        lastName: '',
        email: '',
        password: ''
      }
    };
  },
  methods: {
    registerUser() {
      AuthService.register(this.user).then(response => {
        console.log(response.data);
      });
    }
  }
};
</script>

2.3.3 Create LoginComponent.vue

Create a new file LoginComponent.vue in the src/components directory:

<template>
  <div class="container mt-5">
    <div class="row justify-content-center">
      <div class="col-md-6">
        <div class="card">
          <div class="card-header">Login Form</div>
          <div class="card-body">
            <form @submit.prevent="loginUser">
              <div class="form-group">
                <label>Email</label>
                <input v-model="user.email" class="form-control" type="email" placeholder="Email" />
              </div>
              <div class="form-group">
                <label>Password</label>
                <input v-model="user.password" class="form-control" type="password" placeholder="Password" />
              </div>
              <button type="submit" class="btn btn-primary">Login</button>
            </form>
            <div class="mt-3">
              <span>Not registered? <router-link to="/register">Register/SignUp Here</router-link></span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import AuthService from '../AuthService';

export default {
  data() {
    return {
      user: {
        email: '',
        password: ''
      }
    };
  },
  methods: {
    loginUser() {
      AuthService.login(this.user).then(response => {
        console.log(response.data);
      });
    }
  }
};
</script>

2.3.4 Create App.vue

Modify the App.vue file to include routing for the components:

<template>
  <div id="app">
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <a class="navbar-brand" href="#">Registration and Login System</a>
    </nav>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App'
};
</script>

<style>
nav {
  margin-bottom: 20px;
}
</style>

2.3.5 Update main.js

Ensure the main.js file is set up correctly:

import { createApp } from 'vue';
import App from './App.vue';
import { createRouter, createWebHistory } from 'vue-router';
import RegisterComponent from './components/RegisterComponent.vue';
import LoginComponent from './components/LoginComponent.vue';
import 'bootstrap/dist/css/bootstrap.min.css';

const routes = [
  { path: '/', component: RegisterComponent },
  { path: '/register', component: RegisterComponent },
  { path: '/login', component: LoginComponent }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

const app = createApp(App);
app.use(router);
app.mount('#app');

Step 3: Running the Application

3.1 Run the Spring Boot Application

  1. Open the UserRegistrationApplication class in the src/main/java/com/example/userregistration directory.
  2. Click the green Run button in your IDE or use the terminal to run the application:
    ./mvnw spring-boot:run
    

3.2 Run the Vue.js Application

  1. Open a terminal and navigate to the vue-frontend directory.

  2. Start the Vue application:

    npm run serve
    
  3. Open your web browser and navigate to http://localhost:8080.

You should now be able to register and log in users using the Vue.js frontend and Spring Boot backend.

Conclusion

In this tutorial, we created a full-stack application using Spring Boot for the backend and Vue.js for the frontend. We implemented user registration and login functionalities and handled the necessary configurations to connect the two parts of the application. This setup provides a solid foundation for developing more complex full-stack applications.

Comments