DEV Community

Cover image for ๐Ÿ”‘ Building a Login & Registration System with Spring Boot
Brian Oiko
Brian Oiko

Posted on

๐Ÿ”‘ Building a Login & Registration System with Spring Boot

Authentication is the backbone of any secure web application. Recently, I built a Login Checker using Spring Boot, and in this article, Iโ€™ll walk you through the approach, the code structure, and some best practices. This project covers user registration, login authentication, password hashing, and session-based access control using Spring Security.

๐Ÿš€ Why I Built This

Every developer eventually has to tackle user authentication. Instead of reinventing the wheel, Spring Boot with Spring Security provides powerful tools to handle:

User registration

Login/logout

Password encryption (BCrypt)

Database persistence with JPA & Hibernate

This project was a great opportunity to learn, practice, and share.

๐Ÿ— Project Structure

Hereโ€™s the breakdown of the main components:

1๏ธโƒฃ Model (User Entity)

We created a User entity that maps to the users table in the database.

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String firstName;

    @Column(nullable = false)
    private String lastName;

    @Column(nullable = false, unique = true, updatable = false)
    private String email;

    @Column(nullable = false)
    private String password;

    // Getters & setters
}
Enter fullscreen mode Exit fullscreen mode

2๏ธโƒฃ Repository

Instead of writing SQL manually, we use JpaRepository to talk to the database.

public interface UserRepository extends JpaRepository<User, Long> {
    User findByEmail(String email);
}
Enter fullscreen mode Exit fullscreen mode

3๏ธโƒฃ Service Layer

The service handles user registration a,fetch user details

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    public boolean registerUser(User user) {
        if (userRepository.findByEmail(user.getEmail()) != null) {
            return false; // Email already exists
        }
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userRepository.save(user);
        return true;
    }

    public User findByEmail(String email) {
        return userRepository.findByEmail(email);
    }
}
Enter fullscreen mode Exit fullscreen mode

4๏ธโƒฃ Security Configuration

This is where Spring Security is customized. We allow open access to /register and /login but protect everything else.

@Configuration
public class SecurityConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/register", "/login", "/css/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .defaultSuccessUrl("/welcome", true)
                .permitAll()
            )
            .logout(logout -> logout
                .logoutSuccessUrl("/login?logout")
                .permitAll()
            );
        return http.build();
    }
}
Enter fullscreen mode Exit fullscreen mode

5๏ธโƒฃ Controller

Handles registration, login, and welcome pages.

@Controller
public class WebController {

    @Autowired
    private UserService userService;

    @GetMapping("/register")
    public String showRegistrationForm(Model model) {
        model.addAttribute("user", new User());
        return "register";
    }

    @PostMapping("/register")
    public String registerUser(@ModelAttribute("user") User user, Model model) {
        boolean success = userService.registerUser(user);
        if (!success) {
            model.addAttribute("error", "Email already exists!");
            return "register";
        }
        return "redirect:/login?registered";
    }

    @GetMapping("/login")
    public String loginPage(@RequestParam(value = "registered", required = false) String registered,
                            @RequestParam(value = "logout", required = false) String logout,
                            Model model) {
        if (registered != null) {
            model.addAttribute("message", "Registration successful. Please log in.");
        }
        if (logout != null) {
            model.addAttribute("message", "You have been logged out.");
        }
        return "login";
    }

    @GetMapping("/welcome")
    public String welcome(Model model, Principal principal) {
        String email = principal.getName();
        User user = userService.findByEmail(email);
        model.addAttribute("fullName", user.getFirstName() + " " + user.getLastName());
        return "welcome";
    }
}
Enter fullscreen mode Exit fullscreen mode

โšก Key Features

โœ… User Registration (with validation & duplicate email checks)
โœ… Password Hashing (using BCryptPasswordEncoder)
โœ… Secure Login / Logout (Spring Security)
โœ… Session Handling with Principal
โœ… Welcome Page displaying full user name

๐Ÿ“Š Lessons Learned

Spring Security can feel complex, but configuring a custom SecurityFilterChain makes it clear.

Password hashing is non-negotiable in modern applications. Storing plain-text passwords is a huge risk.

Separating concerns into Model, Repository, Service, and Controller keeps code clean and maintainable.

๐Ÿ’ก Whatโ€™s Next?

๐Ÿ”น Add role-based access control (Admin/User).
๐Ÿ”น Implement email verification.
๐Ÿ”น Integrate JWT tokens for API authentication.
๐Ÿ”น Deploy on Docker + AWS/GCP for production readiness.

๐ŸŽฏ Final Thoughts

This project was a hands-on way to solidify my Spring Boot and Spring Security skills. Authentication is often seen as โ€œjust another feature,โ€ but itโ€™s one of the most critical parts of any application.

Top comments (0)