Spring Boot Spring Security Fundamentals Questions and Answers — Questions and Answers
Question 1: In a modern Spring Boot application, what is the primary purpose of defining a `SecurityFilterChain` bean?
- To define a sequence of security filters that are applied to HTTP requests to handle concerns like authentication, authorization, and CSRF protection. (Correct answer)
- To manage user details and credentials by connecting to a database or an in-memory store.
- To specify how passwords should be hashed and verified during the authentication process.
- To enable method-level security annotations like `@PreAuthorize` and `@Secured` across the application.
Correct answer: To define a sequence of security filters that are applied to HTTP requests to handle concerns like authentication, authorization, and CSRF protection.
The `SecurityFilterChain` is the core component for configuring web-based security. It defines an ordered chain of filters that Spring Security applies to incoming HTTP requests. Each filter has a specific responsibility, such as authenticating a user, checking for a valid CSRF token, or authorizing access to a resource.
Question 2: A developer needs to secure a service method so that it can only be executed by users with the 'ADMIN' role. Which annotation provides the most flexible, expression-based approach to achieve this?
- @Secured("ROLE_ADMIN")
- @RolesAllowed("ADMIN")
- @PreAuthorize("hasRole('ADMIN')") (Correct answer)
- @PermitAll
Correct answer: @PreAuthorize("hasRole('ADMIN')")
The `@PreAuthorize` annotation is the most flexible option as it allows for the use of Spring Expression Language (SpEL). This enables complex authorization rules beyond simple role checks, such as inspecting method arguments or properties of the current user's `Authentication` principal. While `@Secured` and `@RolesAllowed` can check for roles, they do not support expressions.
Question 3: In the context of Spring Security's authentication architecture, what is the primary responsibility of the `AuthenticationManager`?
- To load user-specific data from a persistent store, such as a database.
- To store the authenticated user's details in the `SecurityContext` for the duration of the request.
- To encode and compare passwords using a specific hashing algorithm like bcrypt.
- To coordinate the authentication process by delegating the credential verification to one or more `AuthenticationProvider` instances. (Correct answer)
Correct answer: To coordinate the authentication process by delegating the credential verification to one or more `AuthenticationProvider` instances.
The `AuthenticationManager` acts as the central coordinator for authentication. It receives an `Authentication` object (containing user-submitted credentials) and passes it to a series of configured `AuthenticationProvider`s. Each provider determines if it can handle that type of authentication. If successful, the `AuthenticationManager` returns a fully populated `Authentication` object.
Question 4: A Spring Boot application is configured to use form-based login. To protect against Cross-Site Request Forgery (CSRF) attacks, Spring Security, by default, employs the Synchronizer Token Pattern. How is the CSRF token typically validated for a state-changing request (e.g., POST)?
- The token is sent as a URL query parameter and compared with a value stored in the application's database.
- The browser automatically includes the token from a secure, HttpOnly cookie in the request headers.
- The token, stored in the user's session, must be included by the client in the request as a hidden form field or a specific HTTP header. (Correct answer)
- The server validates that the request's `Origin` header matches the application's domain.
Correct answer: The token, stored in the user's session, must be included by the client in the request as a hidden form field or a specific HTTP header.
By default, Spring Security generates a CSRF token and stores it in the `HttpSession`. For the request to be valid, the client application must include this same token in the request, typically as a hidden input field named `_csrf` or in an HTTP header (like `X-CSRF-TOKEN`). The `CsrfFilter` then compares the token from the request with the one stored in the session to ensure the request is legitimate and not forged.
Question 5: Which of the following is the recommended `PasswordEncoder` implementation in modern Spring Security for securely hashing and storing user passwords?
- `NoOpPasswordEncoder`
- `StandardPasswordEncoder`
- `BCryptPasswordEncoder` (Correct answer)
- `MessageDigestPasswordEncoder`
Correct answer: `BCryptPasswordEncoder`
`BCryptPasswordEncoder` is the recommended and widely used implementation. It uses the bcrypt strong hashing algorithm, which is deliberately slow and includes a randomly generated salt with each hash. This makes it highly resistant to brute-force attacks and rainbow table attacks. `NoOpPasswordEncoder` is for plain text and is insecure, while others are considered legacy.
Question 6: A developer is configuring a `SecurityFilterChain` and wants to ensure that all requests to endpoints starting with `/api/` require authentication, while requests to `/public/` are permitted for everyone. Which of the following configurations correctly implements this requirement?
- `.authorizeHttpRequests(auth -> auth.requestMatchers("/api/**").permitAll().requestMatchers("/public/**").authenticated())`
- `.authorizeHttpRequests(auth -> auth.requestMatchers("/api/**").authenticated().requestMatchers("/public/**").permitAll().anyRequest().denyAll())`
- `.authorizeHttpRequests(auth -> auth.requestMatchers("/public/**").permitAll().requestMatchers("/api/**").authenticated())` (Correct answer)
- `.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())`
Correct answer: `.authorizeHttpRequests(auth -> auth.requestMatchers("/public/**").permitAll().requestMatchers("/api/**").authenticated())`
Spring Security evaluates authorization rules in the order they are declared. To correctly implement the logic, the more specific rule (`/public/**` should be permitted) should be declared before the more general rule (`/api/**` should be authenticated). If `.anyRequest().authenticated()` were first, it would match all requests, and the `/public/**` rule would never be reached. The correct order is to permit the public endpoints first, then secure the API endpoints.
In a modern Spring Boot application, what is the primary purpose of defining a `SecurityFilterChain` bean?