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
}
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);
}
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);
}
}
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();
}
}
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";
}
}
β‘ 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)