WebSecurityConfigurerAdapter
WebSecurityConfigurerAdapter
is used to customize the security configuration of the application. It is an abstract class offered by Spring Security.
By overriding its techniques, it offers a practical means to set security rules and policies.
This class serves as the foundation for extending WebSecurityConfigurerAdapter
-based configuration classes.
In this article, we will understand this class and how it can be used to customize a spring application.
Configuring WebSecurityConfigurerAdapter
To customize the security of your application, you need to create a class and extend WebSecurityConfigurerAdapter
in order to setup Spring Security using this adapter.
Extending this class will provide numerous methods that can be overridden to specify security rules.
To make the Spring Security capabilities available, this class must be annotated with @EnableWebSecurity
.
A basic configuration class that extends WebSecurityConfigurerAdapter
is shown here as an example
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // Configure security rules here } }
Overriding Default Configurations
You can alter the default security configurations by extending WebSecurityConfigurerAdapter
and overriding its configure()
method.
With configure()
method that takes HttpSecurity
as argument, you can control which requests should require authentication, which ones should be allowed without being authenticated, and so on.
You can also create security rules based on URL patterns, HTTP methods, and other factors.
The example that follows shows how to permit access to specific URLs without authentication
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/allow/**").permitAll() .anyRequest().authenticated(); }
In this example, any request starting with /allow/ will be permitted without authentication, while all other requests will require authentication.
Implementing Custom Authentication
To provide unique authentication procedures, use configure()
method of WebSecurityConfigurerAdapter
having AuthenticationManagerBuilder
argument.
In-memory authentication, JDBC-based authentication, and custom userDetailsService are just a few of the authentication providers that can be configured by overriding this function.
You have complete control over how users are authorized in your application by using custom authentication.
Here is an illustration showing how to set up in-memory authentication
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user").password("{noop}password").roles("USER") .and() .withUser("admin").password("{noop}password").roles("ADMIN"); }
In the above example, we configure two users with their passwords and roles.
The {noop} prefix indicates that the passwords are stored in plain text for simplicity. In a production environment, passwords should be properly hashed and secured.
Enabling Method Level Security
Apart from securing URLs, You can secure specific methods within your application with Spring Security.
You can limit access to particular methods based on user roles or other criteria by utilizing method-level security.
To enable method-level security, use @EnableGlobalMethodSecurity
annotation with prePostEnabled
option set to true
over a class that extends WebSecurityConfigurerAdapter
.
Here is an illustration showing how to activate method-level security
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { // Other configurations... }
By enabling prePostEnabled
, you can use annotations like @PreAuthorize
and @PostAuthorize
to define method-level security rules as shown below
@Service public class ProductService { @PreAuthorize("hasRole('ROLE_ADMIN')") public void deleteProduct(Long productId) { // Delete product logic } @PostAuthorize("returnObject.owner == authentication.name") public Product getProduct(Long productId) { // Retrieve product logic return product; } // Other methods }
In this example, the deleteProduct()
method is annotated with @PreAuthorize("hasRole('ROLE_ADMIN')")
, which ensures that only users with the ROLE_ADMIN role can execute this method.
Similarly, the getProduct()
method is annotated with @PostAuthorize("returnObject.owner == authentication.name")
, which ensures that the returned product’s owner matches the authenticated user’s name.
Configuring Form Login
One popular authentication method used in online applications is form-based authentication. For your Spring application, form login may be easily configured using WebSecurityConfigurerAdapter
.
You can provide the login page, the URL used for the login processing, and other relevant options by overriding the configure(HttpSecurity http)
method and utilizing the formLogin()
method.
Here is an illustration showing how to set up form login
@Override protected void configure(HttpSecurity http) throws Exception { http .formLogin() .loginPage("/login") .loginProcessingUrl("/authenticate") .defaultSuccessUrl("/home") .permitAll() .and() .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated(); }
In this example, we configure the login page URL, the URL for processing the login request, and the default success URL after successful authentication.permitAll()
method allows access to the login page without authentication.
With Spring Security you can also control forbidden access when a user tries to access a resource for which they do not have the necessary permissions.
To specify how access forbidden scenarios should be handled, use the configure(HttpSecurity http)
method provided by WebSecurityConfigurerAdapter
.
To handle access refused scenarios, you can modify the access denied page, redirect URLs, or even use custom logic.
Here is an illustration of how to deal with access denied
@Override protected void configure(HttpSecurity http) throws Exception { http .exceptionHandling() .accessDeniedPage("/access-denied") .and() .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated(); }
In this example, we configure the access denied page URL to /access-denied.
If a user tries to access a restricted resource without sufficient privileges, they will be redirected to this page.
Securing RESTful APIs
Spring Security also allows you to secure RESTful APIs in addition to standard web applications.
By specifying the authentication criteria, turning on CSRF protection, and managing authentication failures, the WebSecurityConfigurerAdapter
enables you to setup security for RESTful endpoints.
The antMatchers()
method allows you to specify URL patterns for protecting your APIs.
An illustration of how to protect RESTful APIs is provided here
@Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/api/**").authenticated() .anyRequest().permitAll() .and() .httpBasic(); }
In this example, we disable CSRF protection because it is not required for stateless RESTful APIs.
The antMatchers()
method secures all requests that begin with /api/ and needs authentication.
Other requests are not required to be authenticated.
For added convenience, we offer HTTP Basic authentication.
Remember Me authentication is a useful feature that keeps users logged in even after they close their browser.
You may easily activate and setup Remember Me authentication for your application using WebSecurityConfigurerAdapter
.
You can provide the token validity, remember-me parameter name, and other options by modifying the configure(HttpSecurity http)
method and using the rememberMe()
method.
Here’s an example of how to enable Remember Me authentication
@Override protected void configure(HttpSecurity http) throws Exception { http .rememberMe() .key("uniqueAndSecretKey") .rememberMeParameter("remember-me") .rememberMeCookieName("remember-me-cookie") .tokenValiditySeconds(86400); }
In this example, we configure Remember Me authentication with a unique and secret key, specify the remember-me
parameter name as remember-me, set the cookie name to remember-me-cookie, and set the token validity to 24 hours (86400 seconds).
Integrating with OAuth2
OAuth2 is a very common authorization and authentication protocol.
You can secure your application with OAuth2 providers such as Google, Facebook, and GitHub thanks to Spring Security.
You can define OAuth2 client details, redirect URLs, and other particular parameters for OAuth2 integration by using WebSecurityConfigurerAdapter
.
Below example shows how to use Spring Security to seamlessly integrate your application with OAuth2.
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .oauth2Login() .loginPage("/login") .defaultSuccessUrl("/home") .failureUrl("/login-error") .and() .authorizeRequests() .antMatchers("/home").authenticated() .anyRequest().permitAll(); } }
In this example, we configure OAuth2 login with a custom login page, default success URL, and failure URL. The antMatchers()
method is used to secure the /home page and requires authentication.
Securing Websockets
If your application utilizes Websockets for real-time communication, you may secure them as well.WebSecurityConfigurerAdapter
lets you configure Websocket security by overriding the configure(HttpSecurity http)
method and using the websocket()
method.
You can establish Websocket security rules, enable message-level security, and manage Websocket connection authentication.
Here’s a simple example of how to protect Websockets
@Configuration @EnableWebSocketMessageBroker public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { @Override protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { messages .simpDestMatchers("/secured/**").authenticated() .anyMessage().permitAll(); } // Other configuration options here }
In this example, we configure security for Websockets and restrict access to the “/secured/” destination to authenticated users. All other messages are permitted without authentication.
Conclusion
We explored the role of WebSecurityConfigurerAdapter
in configuring security for Spring applications in this post.
We looked about how to use its different methods to configure security rules, build custom authentication techniques, secure RESTful APIs, and integrate with OAuth2.
You can ensure that your Spring-based apps are secure by following best practices and harnessing the capability of WebSecurityConfigurerAdapter
.