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)