Appearance
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 doEach 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
- A security filter for the chosen method (say, username and password) takes the credentials from the request and builds an
Authenticationobject. It holds the credentials, whether the user is authenticated (not yet:false) and their roles (empty so far). - The filter passes it to the
AuthenticationManager, an interface whose default implementation isProviderManager. It is the bridge between filters and providers: it knows which provider can handle this kind of authentication and delegates to it. - Providers do the actual checking:
DaoAuthenticationProvider: username and password (form login, basic authentication).JwtAuthenticationProvider: JWT tokens.- OAuth2 providers for OAuth2 logins.
DaoAuthenticationProvideruses two helpers:UserDetailsServiceloads the stored user by username. Two implementations come with Spring Security:InMemoryUserDetailsManager(users kept in memory) andJdbcUserDetailsManager(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.
- The provider returns a complete
Authentication: authenticatedtrue, with roles. If the check fails, it throwsBadCredentialsException. - Back in the filter, a successful
Authenticationis stored in theSecurityContext(held bySecurityContextHolder). The request continues to theDispatcherServlet, 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-e1dcb0f2d556Opening any page in a browser redirects to a generated login page at /login.
The methods covered next
- Form login (stateful)
- Basic authentication (stateless)
- JWT (stateless)
- OAuth2: authorization code (stateful or stateless), client credentials (stateless), password grant (stateless)
- 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
- What is the difference between authentication and authorization?
- Where does Spring Security plug into the request flow?
- Does every security filter process every request?
- What does the
AuthenticationManagerdo, and what is its default implementation? - Which provider checks usernames and passwords, and which two helpers does it use?
- How are passwords stored, and how is a login password checked?
- What happens to a successful
Authentication, and how does the controller get it? - What do you get by only adding
spring-boot-starter-security? - When do you need
spring-session-jdbc?
Answers
- Authentication verifies who you are; authorization decides what you may do.
- As a filter in the servlet filter chain (
DelegatingFilterProxy→FilterChainProxy→ the security filter chain), before theDispatcherServlet. - The request passes through all of them, but each acts only when it applies (e.g. the form-login filter only on
POST /login). - It passes the
Authenticationto the provider that can handle it.ProviderManager. DaoAuthenticationProvider, with aUserDetailsServiceand aPasswordEncoder.- As hashes. The raw password from the login is checked against the stored hash by the
PasswordEncoder. - It is stored in the
SecurityContext(viaSecurityContextHolder), which travels with the request to the controller. - All endpoints protected, a user
userwith a generated password printed in the log, and a default login page. - Only to store HTTP sessions in a relational database for stateful authentication.