Skip to the content.

Lesson 1: Authenticating Users in a Legacy Spring Web Application


🎯 Lesson Objectives

By the end of this lesson, you will be able to:

βœ… Understand Our current custom authentication flow

βœ… Identify how user login, logout, and session management are handled

βœ… Recognize the role of AuthenticationFilter and UserAdminPrincipal

βœ… Appreciate the importance of login form validation

βœ… Prepare for modernizing authentication with Spring Security


1️⃣ Current Authentication Architecture

Our current application uses custom authentication logic to protect resources and manage user sessions. Let’s break it down.


πŸ“¦ 1.1 Bootstrap Configuration

com.nicordesigns.site.config.Bootstrap configures our servlet contexts and filters, including:

βœ… Code Snippet:

FilterRegistration.Dynamic authenticationFilter = container.addFilter("authenticationFilter", new AuthenticationFilter());
authenticationFilter.addMappingForUrlPatterns(null, false,
    "/registration", "/registration/*", "/chat", "/chat/*", "/session", "/session/*");

πŸ›‘οΈ 1.2 Authentication Filter

com.nicordesigns.site.filters.AuthenticationFilter is a servlet filter that:

βœ… Checks if the session contains a valid Principal

βœ… Redirects unauthenticated users to the login page (/login)

βœ… Wraps the request to expose the authenticated principal

βœ… Code Snippet:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    HttpSession session = ((HttpServletRequest) request).getSession(false);
    final Principal principal = UserAdminPrincipal.getPrincipal(session);
    if (principal == null) {
        ((HttpServletResponse) response).sendRedirect(((HttpServletRequest) request).getContextPath() + "/login");
    } else {
        chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) request) {
            @Override
            public Principal getUserPrincipal() {
                return principal;
            }
        }, response);
    }
}

πŸ‘€ 1.3 UserAdminPrincipal

com.nicordesigns.site.UserAdminPrincipal manages the user identity:

βœ… Implements Principal

βœ… Stores username

βœ… Provides static helpers to store/retrieve from HttpSession

βœ… Code Snippet:

public static Principal getPrincipal(HttpSession session) {
    return session == null ? null : (Principal) session.getAttribute("com.nicordesigns.user.principal");
}

public static void setPrincipal(HttpSession session, Principal principal) {
    session.setAttribute("com.nicordesigns.user.principal", principal);
}

πŸ”‘ 1.4 Login Form (JSP)

Our login.jsp uses Spring tags for:

βœ… Username and password input

βœ… Field-level and general error messages

βœ… Validation error display

βœ… Example Snippet:

<form:form method="post" modelAttribute="loginForm">
    <form:label path="username">Username</form:label><br/>
    <form:input path="username" /><br/>
    <form:errors path="username" cssClass="errors" />

    <form:label path="password">Password</form:label><br/>
    <form:password path="password" /><br/>
    <form:errors path="password" cssClass="errors" /><br/>

    <input type="submit" value="Login" />
</form:form>

βš™οΈ 1.5 AuthenticationController

The AuthenticationController (com.nicordesigns.site.AuthenticationController) manages:

βœ… Login

βœ… Logout

βœ… Login form validation

βœ… Session creation & management

βœ… Key Features:

βœ… Code Snippet:

@PostMapping(value = "login")
public ModelAndView login(@ModelAttribute("loginForm") @Valid LoginForm form,
                          Errors errors,
                          Map<String, Object> model,
                          HttpSession session,
                          HttpServletRequest request) {
    log.info("login POST");

    if (UserAdminPrincipal.getPrincipal(session) != null)
        return getRegistrationRedirect();

    if (errors.hasErrors()) {
        form.setPassword(null);
        return new ModelAndView("login");
    }

    Principal principal;
    try {
        principal = authenticationService.authenticate(form.getUsername(), form.getPassword());
    } catch (ConstraintViolationException e) {
        form.setPassword(null);
        model.put("validationErrors", e.getConstraintViolations());
        return new ModelAndView("login");
    }

    if (principal == null) {
        form.setPassword(null);
        model.put("loginFailed", true);
        return new ModelAndView("login");
    }

    UserAdminPrincipal.setPrincipal(session, principal);
    request.changeSessionId();
    return getRegistrationRedirect();
}

πŸ›‘ Current Flow Summary

βœ… Login:

βœ… Session Validation:

βœ… Logout:


πŸš€ Next Steps

Now that we have fully documented our existing login and authentication approach, we’re ready to:

βœ… Identify gaps in security (e.g., CSRF protection, concurrent sessions)

βœ… Integrate Spring Security gradually, starting with basic SecurityFilterChain to standardize authentication

βœ… Migrate existing AuthenticationController logic to Spring Security’s form login flow