Spring Security is a really powerful tool, but to start using it in your project you need to turn on the security machinery. The @EnableWebSecurity annotation, as the name suggests, does exactly that.
In short, @EnableWebSecurity:
- enables the use of Spring Security in your application.
- hooks up security configuration either via the
WebSecurityConfigurerAdapterclass or directly viaSecurityFilterChain. - initializes Spring Security filters to handle all incoming HTTP requests.
Without it, Spring Security will sit in your project like a museum piece — nice to look at but not very useful. Let's see how it works and why it's so important.
What happens after you add @EnableWebSecurity?
Want to know what happens when you add @EnableWebSecurity to your code? Spring Security wakes up and starts guarding your app! Let's peek under the hood of that magic:
- Spring creates a chain of security filters — basically a checkpoint for all incoming requests. Each request now goes through this security system before it reaches your application.
- Spring Security immediately enables basic protection — like putting locks on all the doors. By default all HTTP resources become locked down, and without the right "keys" (authentication) you can't get to them.
- And the coolest part — you can customize this security system to fit your needs! Want to add your own checks? Use
SecurityFilterChain.
And if you're curious about history, people used to do this with WebSecurityConfigurerAdapter (though since version 5.7 it's pretty much considered vintage).
Basics of configuration with @EnableWebSecurity
Here's an example of the minimal security configuration:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
// Config is empty for now, but security is already turned on!
}
If you run this app and try to access any of your resource or controller URLs, you'll notice Spring Security automatically redirects you to a login page. That's the default behavior, provided out-of-the-box.
Customizing the configuration
Let's add some meaningful customization. We can override settings using a SecurityFilterChain bean:
Example with custom rules:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests() // Configure request authorization
.antMatchers("/public/**").permitAll() // Allow access to all URLs starting with /public
.anyRequest().authenticated() // All other requests require authentication
.and()
.formLogin() // Enable the standard login form
.loginPage("/login") // Custom login page
.permitAll()
.and()
.logout() // Enable the standard logout
.permitAll();
return http.build();
}
}
Let's break down what this code does:
- Restricting access by URL: the
antMatchersmethods let you define access based on specific URLs. For example, all requests to/publicare allowed without authentication. - Login form: we've customized the default login form by pointing to our page with
loginPage. Now users will see your custom UI instead of the default login page. - Logout: we allow any user to perform logout.
After adding this configuration, your app will be protected in a more meaningful way than with Spring Security's basic defaults.
Why was WebSecurityConfigurerAdapter needed?
We already mentioned that before Spring Security 5.7, security customization was usually done by extending WebSecurityConfigurerAdapter. Here's what that looked like:
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
If you still see this approach in old code — don't freak out. But get used to using SecurityFilterChain, since that approach is more modern.
Examples of basic security setup
1. Simple example where all pages are protected:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin() // Enable login form
.and()
.httpBasic(); // This adds support for HTTP Basic authentication
return http.build();
}
}
Now when trying to access any resource, the user will have to either enter credentials in the browser or authenticate via HTTP Basic.
2. Example with public resources:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/images/**").permitAll() // Open static resources
.antMatchers("/", "/home").permitAll() // Open the home page
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
return http.build();
}
}
This example lets certain public resources (like static assets or the home page) be viewed, while protecting everything else.
Common mistakes and how to fix them
- Mistake: you lock down everything, including the login page. If you configure things incorrectly, you might accidentally block access to your own login page. Make sure the login page (or other public resources) is explicitly allowed via
permitAll(). - Mistake: you forgot to add
@EnableWebSecurity. Without that annotation your configuration won't be applied and the app just won't be secured. - Mistake: using the outdated
WebSecurityConfigurerAdapterapproach. With the move to the modernSecurityFilterChain, a lot of online examples can be misleading. Use newer Spring Security versions to avoid compatibility issues.
Practice: setting up a basic configuration
Let's add security to our tutorial app. Imagine we have a web app for managing books. We need to:
- Create a login page.
- Allow everyone to access
/loginand/register. - Protect access to all other pages.
Configuration:
@Configuration
@EnableWebSecurity
public class BookAppSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/register").permitAll() // Access for everyone
.anyRequest().authenticated() // Everything else requires authentication
.and()
.formLogin() // Enable the standard login form
.loginPage("/login") // Point to custom login page
.permitAll()
.and()
.logout()
.permitAll(); // Logout is available to everyone
return http.build();
}
}
Now our app is secure: users can register or log in, but without authentication access to other pages is blocked.
Link to the Spring Security documentation to dig deeper.
GO TO FULL VERSION