Correct use of WebSecurity in WebSecurityConfigurerAdapter
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When developers override configure(WebSecurity web) in a WebSecurityConfigurerAdapter, they often use it for the wrong job. The method exists to remove requests from the Spring Security filter chain entirely, which is much more drastic than merely allowing anonymous access. That distinction is the key to using it correctly in legacy Spring Security applications.
What WebSecurity Actually Does
WebSecurityConfigurerAdapter exposes three main customization points:
- '
configure(HttpSecurity http)defines authorization rules and login behavior.' - '
configure(AuthenticationManagerBuilder auth)defines how users are authenticated.' - '
configure(WebSecurity web)tells Spring Security to ignore matching requests completely.'
That last point is easy to misuse. If you write web.ignoring().antMatchers("/api/public/**"), those requests skip every security filter. That means no authentication, no authorization decisions, no CSRF checks, no security headers added by Spring Security, and no SecurityContext setup. For static assets, that can be fine. For API endpoints, it is usually the wrong choice.
The Correct Split Between WebSecurity and HttpSecurity
Use WebSecurity for resources that genuinely do not need the filter chain, such as images, stylesheets, JavaScript bundles, or favicon files. Use HttpSecurity for application endpoints, even if they are publicly accessible.
A typical legacy configuration looks like this:
In this version, /api/public/** is still processed by Spring Security, but authorization allows anonymous users through. That is usually what you want, because it preserves consistent behavior for logging, exception handling, and response hardening.
Why permitAll() Is Different From Ignoring
permitAll() means "let this request through after the filter chain evaluates it." Ignoring means "pretend Spring Security does not exist for this request." Those are not equivalent.
Suppose your app serves a public registration endpoint. If you ignore it through WebSecurity, you lose useful framework behavior. If you mark it with permitAll(), the request stays inside the normal processing pipeline and still benefits from the rest of your security setup.
This is especially important for modern applications that rely on:
- custom exception translation
- audit logging tied to filters
- header writers such as cache or frame settings
- CSRF for browser-submitted forms
For public business endpoints, permitAll() is safer and more maintainable.
A Better Pattern for Static Resources
If your goal is only to make CSS and JavaScript reachable before login, keep the ignore list narrow and obvious. A small ignore list is easier to audit than a broad wildcard such as "/**/public/**", which can accidentally hide sensitive controllers from the filter chain.
You can also express static-resource rules through Spring helpers when available:
That makes intent clearer and reduces the chance of path mistakes.
Migration Note for Newer Spring Security
WebSecurityConfigurerAdapter is deprecated in newer Spring Security releases. The modern style is to expose a SecurityFilterChain bean and optionally a WebSecurityCustomizer bean. The underlying rule is still the same: ignore only true static resources, and use authorization rules for real endpoints.
Here is the equivalent idea in the component-based style:
Common Pitfalls
The most common mistake is putting public controller routes in web.ignoring(). That bypasses all security filters and often creates behavior that is inconsistent with the rest of the application.
Another common problem is using very broad path patterns for static resources. A pattern that is too loose can accidentally expose endpoints that were supposed to stay protected.
Developers also forget that examples using {noop} passwords are only for demos. In a real application, use a password encoder such as BCrypt and store hashed passwords.
Finally, many teams are still copying WebSecurityConfigurerAdapter examples into projects that no longer need it. If you are starting new code, prefer the bean-based configuration model and keep the same separation of concerns.
Summary
- '
configure(WebSecurity web)removes matching requests from the security filter chain.' - Use it for static resources, not for normal application or API endpoints.
- Use
permitAll()inHttpSecuritywhen an endpoint should stay public but still pass through security filters. - Keep ignore rules narrow so they are easy to reason about and audit.
- In newer Spring Security versions, the same principle applies even though
WebSecurityConfigurerAdapteris deprecated.

