Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Interview Prep: 2–5 Years

Revise the Fresher Tier

  • Revise: Core Java Fundamentals (Fresher Tier)
  • Revise: Collections, Threads, Java 8 & Coding (Fresher Tier)
  • Revise: Spring Core, Spring Boot & Spring MVC (Fresher Tier)
  • Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Intermediate Core Java

  • Intermediate OOP & Language Features — Interview Questions
  • Enums, Generics, Pass-by-Value & Imports — Interview Questions
  • Collections Internals & Scenarios — Interview Questions
  • JVM, Memory & Class Loading — Interview Questions
  • Exception Design & Serialization Edge Cases — Interview Questions

Java 8 Deep Dive & Stream Coding

  • Lambdas, Functional Interfaces & Method References — Interview Questions
  • Default Methods, Backward Compatibility & Optional — Interview Questions
  • Stream API Internals (Part 1) — Interview Questions
  • Stream API Internals (Part 2) — Interview Questions
  • Stream Coding Problems (Level 2, Part 1) — Interview Questions
  • Stream Coding Problems (Level 2, Part 2) — Interview Questions

Concurrency & Multithreading

  • Synchronization, Locks & Deadlocks — Interview Questions
  • Executors, ThreadLocal & Concurrent Collections — Interview Questions

Spring Framework In Depth

  • Bean Lifecycle, Contexts & Circular Dependencies — Interview Questions
  • Spring Bean Conflicts, AOP, Batch & Injection Styles — Interview Questions

Spring Boot In Depth & Scenarios

  • Spring Boot Internals & Auto-Configuration — Interview Questions
  • Spring Boot Configuration, Profiles & Secrets — Interview Questions
  • Spring Boot Data, Transactions & Caching — Interview Questions
  • Spring Boot Testing, Error Pages & Deployment — Interview Questions
  • Spring Boot Performance, Scaling & Resilience — Interview Questions
  • Spring Boot Async, Events & Messaging — Interview Questions
  • Spring Boot Security Scenarios — Interview Questions
  • Actuator, AOP, Spring Cloud & Distributed Tracing — Interview Questions
  • External APIs, Files, GraphQL & WebFlux — Interview Questions

Spring Security

  • Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions
  • Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Apache Kafka

  • Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions
  • Kafka Producers, Consumers, Reliability & Streams — Interview Questions
  • Kafka Security, Connect & Core Scenarios — Interview Questions
  • Kafka Production Scenarios — Interview Questions

Git, Maven & Gradle (Level II)

  • Git Workflows, Rebase & Conflict Handling — Interview Questions
  • Git Recovery, Hooks, Tags & Collaboration — Interview Questions
  • Maven Builds, Multi-Module Projects & Dependency Resolution — Interview Questions
  • Maven Profiles, settings.xml, Plugins & Quality Gates — Interview Questions
  • Gradle Fundamentals, Migration & Dependencies — Interview Questions
  • Gradle Performance, Plugins, Testing & Publishing — Interview Questions

Deployment & CI/CD

  • Sessions, CI/CD Pipelines, Rollbacks & Secrets — Interview Questions
  • Migrations, Zero-Downtime Releases, Containers & Monitoring — Interview Questions

JUnit 5 & Mockito

  • JUnit 5 — Interview Questions
  • Mockito Basics — Interview Questions
  • Mockito Advanced & Tricky Questions — Interview Questions
Chaturmind
← Java Interview Prep: 2–5 Years

Revise the Fresher Tier

  • Revise: Core Java Fundamentals (Fresher Tier)
  • Revise: Collections, Threads, Java 8 & Coding (Fresher Tier)
  • Revise: Spring Core, Spring Boot & Spring MVC (Fresher Tier)
  • Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Intermediate Core Java

  • Intermediate OOP & Language Features — Interview Questions
  • Enums, Generics, Pass-by-Value & Imports — Interview Questions
  • Collections Internals & Scenarios — Interview Questions
  • JVM, Memory & Class Loading — Interview Questions
  • Exception Design & Serialization Edge Cases — Interview Questions

Java 8 Deep Dive & Stream Coding

  • Lambdas, Functional Interfaces & Method References — Interview Questions
  • Default Methods, Backward Compatibility & Optional — Interview Questions
  • Stream API Internals (Part 1) — Interview Questions
  • Stream API Internals (Part 2) — Interview Questions
  • Stream Coding Problems (Level 2, Part 1) — Interview Questions
  • Stream Coding Problems (Level 2, Part 2) — Interview Questions

Concurrency & Multithreading

  • Synchronization, Locks & Deadlocks — Interview Questions
  • Executors, ThreadLocal & Concurrent Collections — Interview Questions

Spring Framework In Depth

  • Bean Lifecycle, Contexts & Circular Dependencies — Interview Questions
  • Spring Bean Conflicts, AOP, Batch & Injection Styles — Interview Questions

Spring Boot In Depth & Scenarios

  • Spring Boot Internals & Auto-Configuration — Interview Questions
  • Spring Boot Configuration, Profiles & Secrets — Interview Questions
  • Spring Boot Data, Transactions & Caching — Interview Questions
  • Spring Boot Testing, Error Pages & Deployment — Interview Questions
  • Spring Boot Performance, Scaling & Resilience — Interview Questions
  • Spring Boot Async, Events & Messaging — Interview Questions
  • Spring Boot Security Scenarios — Interview Questions
  • Actuator, AOP, Spring Cloud & Distributed Tracing — Interview Questions
  • External APIs, Files, GraphQL & WebFlux — Interview Questions

Spring Security

  • Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions
  • Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Apache Kafka

  • Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions
  • Kafka Producers, Consumers, Reliability & Streams — Interview Questions
  • Kafka Security, Connect & Core Scenarios — Interview Questions
  • Kafka Production Scenarios — Interview Questions

Git, Maven & Gradle (Level II)

  • Git Workflows, Rebase & Conflict Handling — Interview Questions
  • Git Recovery, Hooks, Tags & Collaboration — Interview Questions
  • Maven Builds, Multi-Module Projects & Dependency Resolution — Interview Questions
  • Maven Profiles, settings.xml, Plugins & Quality Gates — Interview Questions
  • Gradle Fundamentals, Migration & Dependencies — Interview Questions
  • Gradle Performance, Plugins, Testing & Publishing — Interview Questions

Deployment & CI/CD

  • Sessions, CI/CD Pipelines, Rollbacks & Secrets — Interview Questions
  • Migrations, Zero-Downtime Releases, Containers & Monitoring — Interview Questions

JUnit 5 & Mockito

  • JUnit 5 — Interview Questions
  • Mockito Basics — Interview Questions
  • Mockito Advanced & Tricky Questions — Interview Questions
HomeLearnJava Interview PrepJava Interview Prep: 2–5 YearsSpring Security
✓ FreeIntermediate· 8 min read

Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Storing passwords (BCrypt/Argon2, DelegatingPasswordEncoder), the security filter chain and custom filters, session management and concurrent-session control, debugging unexpected 403s, dynamic access-control policies, testing security, salting, AuthenticationManager vs ProviderManager, and custom access-denied handling.

Published September 25, 2026


How to use this lesson

The second half of Spring Security is about internals and operations: how authentication is actually performed, where filters sit, how sessions behave, and how to debug a baffling 403. These are exactly the things you only learn by running Spring Security in production.

Q1. What's the best practice for storing passwords?

Short answer: Never store passwords in plaintext, or reversibly. Store a hash from a slow, salted, adaptive algorithm: BCrypt (Spring's default), Argon2id, scrypt or PBKDF2. Use DelegatingPasswordEncoder, which prefixes each hash with its algorithm ({bcrypt}$2a$10$…). You can then upgrade algorithms later, and existing hashes keep working.

@Bean
PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();    // {bcrypt} by default
}
// registration: user.setPasswordHash(encoder.encode(rawPassword));
// login: handled by DaoAuthenticationProvider → encoder.matches(raw, stored)

Key points to cover:

  • Tune the work factor, so hashing takes roughly 100 ms or more on your hardware.
  • Implement UserDetailsPasswordService, so Spring re-hashes passwords transparently at login when you raise the strength.
  • Also rate-limit logins, check new passwords against breached-password lists, and support MFA.

Learn it in depth → Password Encoding

Q2. What does the Spring Security filter chain do, and how do you add a custom filter?

Short answer: Every request passes through DelegatingFilterProxy → FilterChainProxy, which picks the first matching SecurityFilterChain, and runs its ordered filters. Among them:

  • SecurityContextHolderFilter;
  • CSRF;
  • logout;
  • the authentication filters (form, Basic, bearer token);
  • ExceptionTranslationFilter (turns security exceptions into 401/403 responses or login redirects);
  • AuthorizationFilter, last.

To add your own filter, write a filter (usually OncePerRequestFilter), and place it relative to a known filter:

@Bean
SecurityFilterChain api(HttpSecurity http, ApiKeyFilter apiKeyFilter) throws Exception {
    return http
        .addFilterBefore(apiKeyFilter, UsernamePasswordAuthenticationFilter.class)   // or addFilterAfter / addFilterAt
        .authorizeHttpRequests(a -> a.anyRequest().authenticated())
        .build();
}

Common trap: annotating the custom filter as a @Component and adding it to the chain. Spring Boot then also registers it as a regular servlet filter, so it runs twice. Declare it with a FilterRegistrationBean that has setEnabled(false), or don't make it a bean.

Learn it in depth → Authentication Mechanics

Q3. How does Spring Security handle session management, and how do you control concurrent sessions?

Short answer:

  • Creation policy: ALWAYS, IF_REQUIRED (the default), NEVER, or STATELESS (for token APIs).
  • Session-fixation protection: the session ID changes at login (changeSessionId, the default).
  • Invalid or expired session handling, and timeouts.
  • Concurrency control: maximumSessions(n), with either maxSessionsPreventsLogin(true) (block new logins) or the default behaviour (expire the oldest session).
http.sessionManagement(s -> s
        .sessionFixation(f -> f.changeSessionId())
        .maximumSessions(1)
        .maxSessionsPreventsLogin(false)            // the new login kicks out the old session
        .expiredUrl("/login?expired"));

Key points to cover:

  • Concurrent-session control needs a SessionRegistry. In a cluster, use Spring Session (for example FindByIndexNameSessionRepository with Redis), so the limits apply across instances.

Q4. Users are unexpectedly denied access to a resource they should reach. How do you debug it?

Short answer: Work through it systematically:

  1. Turn on security logging: logging.level.org.springframework.security=TRACE. It logs which SecurityFilterChain matched, each filter, and why authorisation failed.
  2. Check authentication. Is it a 401 (not authenticated: expired token, missing header, a CORS preflight blocked) or a 403 (authenticated, but not authorised)?
  3. Inspect the actual authorities: log authentication.getAuthorities(). Common causes:
    • a missing ROLE_ prefix (hasRole('ADMIN') vs the authority ADMIN);
    • JWT claims not mapped to authorities;
    • scopes arriving as SCOPE_x.
  4. Check the rule order. An earlier matcher may be catching the request, or the request may be matched by a different filter chain (securityMatcher).
  5. Check CSRF. A 403 on a POST often means a missing CSRF token.
  6. Check method security. @PreAuthorize expressions, and proxies (self-invocation).
  7. Reproduce in a test with the same user and authorities (@WithMockUser, jwt()).

Q5. How do you implement dynamic access-control policies?

Short answer: When the rules live in data (a permissions table, per-tenant policies, or feature entitlements) rather than code:

  • Implement a custom AuthorizationManager<RequestAuthorizationContext> for URL rules, or AuthorizationManager<MethodInvocation> for methods, which loads the policies (cached) and decides.
  • Or call a policy bean from SpEL (@PreAuthorize("@policy.can(authentication, 'invoice:approve', #invoiceId)")).
  • Or delegate to an external policy engine (OPA/Rego, Cerbos) for centralised, auditable rules.
@Bean
SecurityFilterChain api(HttpSecurity http, DynamicUrlAuthorizationManager dynamicRules) throws Exception {
    return http.authorizeHttpRequests(a -> a
                    .requestMatchers("/api/public/**").permitAll()
                    .anyRequest().access(dynamicRules))                 // rules loaded from the DB, and cached
               .build();
}

Key points to cover:

  • Cache the policies, and invalidate the cache when they change. Otherwise every request hits the policy database.

Q6. How do you test security configurations?

Short answer: With spring-security-test, combined with @WebMvcTest or @SpringBootTest:

  • @WithMockUser(roles = "ADMIN"), @WithAnonymousUser and @WithUserDetails, for method or MVC tests.
  • MockMvc request post-processors: .with(jwt().authorities(...)), .with(csrf()), .with(user("u").roles("USER")).
  • Assert both sides: allowed users get 200, others get 401 or 403. Include CSRF and CORS cases.
@WebMvcTest(AdminController.class)
@Import(SecurityConfig.class)
class AdminSecurityTest {
    @Autowired MockMvc mvc;

    @Test void anonymousIs401() throws Exception { mvc.perform(get("/api/admin/stats")).andExpect(status().isUnauthorized()); }
    @Test void userIs403() throws Exception {
        mvc.perform(get("/api/admin/stats").with(jwt().authorities(new SimpleGrantedAuthority("ROLE_USER"))))
           .andExpect(status().isForbidden());
    }
    @Test void adminIs200() throws Exception {
        mvc.perform(get("/api/admin/stats").with(jwt().authorities(new SimpleGrantedAuthority("ROLE_ADMIN"))))
           .andExpect(status().isOk());
    }
}

Q7. What is salting, and how is it used in Spring Security?

Short answer: A salt is a random value generated per password, and combined with it before hashing. Identical passwords then get different hashes, and precomputed rainbow tables become useless. Attackers have to crack each hash separately.

Key points to cover:

  • You don't manage salts yourself in Spring Security. BCrypt, Argon2 and PBKDF2 encoders generate a random salt, and embed it inside the resulting hash string. matches() extracts it again to verify.
  • A pepper is a separate secret added on top of the salt, and stored outside the database (for example, in an HSM or KMS).

Q8. How can you use SpEL for fine-grained access control? (Asked again: a real example)

Short answer: Here's a realistic banking rule, with a limit that depends on the caller's role:

@PreAuthorize("""
    hasRole('TELLER') and #amount <= 50000
    or hasRole('BRANCH_MANAGER') and #amount <= 1000000
    or hasRole('TREASURY')""")
public Transfer approveTransfer(long transferId, BigDecimal amount) { … }

Key points to cover:

  • Once expressions grow like this, move them into a policy bean, and unit-test the policy directly. SpEL strings aren't checked by the compiler, and typos fail only at runtime.

Q9. What are AuthenticationManager and ProviderManager?

Short answer: AuthenticationManager is the interface with a single method, authenticate(Authentication), which returns a fully authenticated token or throws AuthenticationException. ProviderManager is its main implementation. It holds a list of AuthenticationProviders, and asks each one that supports the token type:

  • DaoAuthenticationProvider for username and password, through UserDetailsService + PasswordEncoder;
  • JwtAuthenticationProvider for bearer tokens;
  • LDAP providers, and so on.

The first provider to succeed wins. If none can handle the token, it delegates to an optional parent manager.

@Bean
AuthenticationManager authenticationManager(UserDetailsService uds, PasswordEncoder encoder) {
    var dao = new DaoAuthenticationProvider(encoder);
    dao.setUserDetailsService(uds);
    return new ProviderManager(dao);                 // add more providers, e.g. an LDAP one, for multiple login methods
}

Q10. How do you redirect unauthorised users to a custom "access denied" page?

Short answer: Configure the ExceptionTranslationFilter handlers:

  • For authenticated users without permission, set an AccessDeniedHandler, or simply accessDeniedPage("/access-denied").
  • For unauthenticated users, set an AuthenticationEntryPoint. It redirects to the login page for web apps, or returns a 401 JSON Problem Detail for APIs.
http.exceptionHandling(e -> e
        .accessDeniedPage("/access-denied")                                         // web app: a friendly 403 page
        .defaultAuthenticationEntryPointFor(
            new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED),
            PathPatternRequestMatcher.withDefaults().matcher("/api/**")));          // APIs: plain 401, no redirect

Key points to cover:

  • For APIs, return JSON (Problem Details) from a custom AccessDeniedHandler, rather than redirecting.

Follow-up questions this topic invites — and their answers

Q: Why is BCrypt slow on purpose? A: Slowness limits how many guesses per second an attacker can make against stolen hashes. A normal login barely notices 100 ms, but an offline attacker's cost goes up enormously.

Q: Can one application have several SecurityFilterChains? A: Yes. Order them with @Order, and scope each with securityMatcher(...). For example, one chain for /api/** (stateless JWT), and another for the web UI (form login, sessions).

Q: How do you log out a JWT-authenticated user? A: The client discards the tokens, and the identity provider revokes the refresh token. Access tokens stay valid until they expire, which is why they're kept short-lived. Use a denylist if you need immediate revocation.

Q: What's ExceptionTranslationFilter responsible for? A: It catches AuthenticationException (starting authentication through the entry point: a 401 or a login redirect) and AccessDeniedException (a 403 through the access-denied handler), for exceptions thrown further down the chain.

Previous

Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions

Next

Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions

AI Tutor

Lesson: Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Quick actions

AI responses can be inaccurate. Verify critical information.