Skip to content
Chapter 34 · Spring Boot

Spring Security Part 1: Architecture and Setup ​

Applications face attacks such as CSRF (cross-site request forgery), XSS (cross-site scripting) and SQL injection; the chapter on attacks demonstrates them, along with CORS (cross-origin resource sharing), a browser mechanism that becomes a hole when configured too loosely. To protect resources you need two things:

  • Authentication: verify who you are, for example with a username and password.
  • Authorization: check what you are allowed to do. An authenticated user may be allowed to view a page but not to change it.

Spring Security provides both.

Where Spring Security fits ​

From the filters chapter, a request flows like this:

Adding Spring Security inserts one more filter into that chain (a DelegatingFilterProxy). It hands the request to Spring Security's FilterChainProxy, which runs the security filter chain: a list of security filters. With the default setup in Spring Boot 3.3:

DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextHolderFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
UsernamePasswordAuthenticationFilter     form login
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
BasicAuthenticationFilter                basic authentication
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
AuthorizationFilter                      checks what you are allowed to do

Each authentication method has its own filter: form login uses UsernamePasswordAuthenticationFilter, basic authentication uses BasicAuthenticationFilter, JWT and OAuth2 add others. The chain contains only the filters for the methods you configure. A request passes through the chain, and each filter decides whether it applies: UsernamePasswordAuthenticationFilter acts only on the login form's POST /login, and just passes other requests along.

The authentication flow ​

  1. A security filter for the chosen method (say, username and password) takes the credentials from the request and builds an Authentication object. It holds the credentials, whether the user is authenticated (not yet: false) and their roles (empty so far).
  2. The filter passes it to the AuthenticationManager, an interface whose default implementation is ProviderManager. It is the bridge between filters and providers: it knows which provider can handle this kind of authentication and delegates to it.
  3. Providers do the actual checking:
    • DaoAuthenticationProvider: username and password (form login, basic authentication).
    • JwtAuthenticationProvider: JWT tokens.
    • OAuth2 providers for OAuth2 logins.
  4. DaoAuthenticationProvider uses two helpers:
    • UserDetailsService loads the stored user by username. Two implementations come with Spring Security: InMemoryUserDetailsManager (users kept in memory) and JdbcUserDetailsManager (users in a database).
    • PasswordEncoder: Spring stores passwords hashed, never in plain text. The password is hashed when the user is created; at login, the raw password is checked against the stored hash.
  5. The provider returns a complete Authentication: authenticated true, with roles. If the check fails, it throws BadCredentialsException.
  6. Back in the filter, a successful Authentication is stored in the SecurityContext (held by SecurityContextHolder). The request continues to the DispatcherServlet, interceptors and the controller, which can read the logged-in user from the security context.

Treat this as a template. Each authentication method in the next parts follows it, adding or skipping a step: which filter runs, which provider, what goes into the Authentication object and the security context.

Setup ​

In an existing project, add:

xml
<!-- authentication, authorization, the security filters -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- optional: store HTTP sessions in a relational database (for stateful login, later) -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-jdbc</artifactId>
</dependency>

For a new project, choose Spring Web and Spring Security at start.spring.io (and JDBC Session, only if sessions must be stored in a database).

With just the security starter, every endpoint is protected. Spring Boot creates one user, user, and logs a random password at startup:

Using generated security password: dcfcaf08-8149-4e4f-86a6-e1dcb0f2d556

Opening any page in a browser redirects to a generated login page at /login.

The methods covered next ​

  1. Form login (stateful)
  2. Basic authentication (stateless)
  3. JWT (stateless)
  4. OAuth2: authorization code (stateful or stateless), client credentials (stateless), password grant (stateless)
  5. API key authentication (stateless)

Next: Every login method checks a username and password against stored users, so users must exist first. Part 2 covers creating them, in memory and in a database, with hashed passwords.

Check yourself ​

  1. What is the difference between authentication and authorization?
  2. Where does Spring Security plug into the request flow?
  3. Does every security filter process every request?
  4. What does the AuthenticationManager do, and what is its default implementation?
  5. Which provider checks usernames and passwords, and which two helpers does it use?
  6. How are passwords stored, and how is a login password checked?
  7. What happens to a successful Authentication, and how does the controller get it?
  8. What do you get by only adding spring-boot-starter-security?
  9. When do you need spring-session-jdbc?
Answers
  1. Authentication verifies who you are; authorization decides what you may do.
  2. As a filter in the servlet filter chain (DelegatingFilterProxy → FilterChainProxy → the security filter chain), before the DispatcherServlet.
  3. The request passes through all of them, but each acts only when it applies (e.g. the form-login filter only on POST /login).
  4. It passes the Authentication to the provider that can handle it. ProviderManager.
  5. DaoAuthenticationProvider, with a UserDetailsService and a PasswordEncoder.
  6. As hashes. The raw password from the login is checked against the stored hash by the PasswordEncoder.
  7. It is stored in the SecurityContext (via SecurityContextHolder), which travels with the request to the controller.
  8. All endpoints protected, a user user with a generated password printed in the log, and a default login page.
  9. Only to store HTTP sessions in a relational database for stateful authentication.