Course – LSS – NPI (cat=Security/Spring Security)
announcement - icon

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security:

>> CHECK OUT THE COURSE

1. Overview

This article is an introduction to Java configuration for Spring Security which enables users to easily configure Spring Security without the use of XML.

Java configuration was added to the Spring framework in Spring 3.1 and extended to Spring Security in Spring 3.2 and is defined in a class annotated @Configuration.

2. Maven Setup

To use Spring Security in a Maven projects, we first need to have the spring-security-core dependency in the project pom.xml:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>5.3.3.RELEASE</version>
</dependency>

The latest version can always be found here.

3. Web Security With Java Configuration

Let’s start with a basic example of a Spring Security Java configuration:

@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.inMemoryAuthentication().withUser("user")
          .password(passwordEncoder().encode("password")).roles("USER");
    }
}

As you may have noticed, the configuration sets up a basic in-memory authentication config. Additionally, starting Spring 5, we need a PasswordEncoder bean:

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

4. HTTP Security

To enable HTTP Security in Spring, we need to create a SecurityFilterChain bean :

@Bean 
 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests()
      .anyRequest().authenticated()
      .and().httpBasic();
    return http.build();
}

The above configuration makes sure any request to the application is authenticated with form based login or HTTP basic authentication.

Also, it is exactly similar to the following XML configuration:

<http>
    <intercept-url pattern="/**" access="isAuthenticated()"/>
    <form-login />
    <http-basic />
</http>

5. Form Login

Interestingly, Spring Security generates a login page automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests()
      .anyRequest().authenticated()
      .and().formLogin()
      .loginPage("/login").permitAll();
    return http.build();
}

Here the automatically generated login page is convenient to get up and running quickly.

6. Authorization With Roles

Let’s now configure some simple authorization on each URL using roles:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests()
      .antMatchers("/", "/home").access("hasRole('USER')")
      .antMatchers("/admin/**").hasRole("ADMIN")
      .and()
      // some more method calls
      .formLogin();
    return http.build();
}

Notice how we’re using both the type-safe API – hasRole – but also the expression based API, via access.

7. Logout

As many other aspects of Spring Security, logout has some great defaults provided by the framework.

By default, a logout request invalidates the session, clears any authentication caches, clears the SecurityContextHolder and redirects to login page.

Here is a simple logout config:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.logout();
    return http.build();
}

However, if you want to get more control over the available handlers, here’s what a more complete implementation will look like:

@Bean
 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.logout().logoutUrl("/my/logout")
      .logoutSuccessUrl("/my/index")
      .logoutSuccessHandler(logoutSuccessHandler) 
      .invalidateHttpSession(true)
      .addLogoutHandler(logoutHandler)
      .deleteCookies(cookieNamesToClear)
      .and()
      // some other method calls
    return http.build();
}

8. Authentication

Let’s have a look at another way of allowing authentication with Spring Security.

8.1. In-Memory Authentication

We’ll start with a simple, in-memory configuration:

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) 
  throws Exception {
    auth.inMemoryAuthentication()
      .withUser("user").password(passwordEncoder().encode("password")).roles("USER")
      .and()
      .withUser("admin").password(passwordEncoder().encode("password")).roles("USER", "ADMIN");
}

8.2. JDBC Authentication

To move that to JDBC, all you have to do is to define a data source within the application – and use that directly:

@Autowired
private DataSource dataSource;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) 
  throws Exception {
    auth.jdbcAuthentication().dataSource(dataSource)
      .withDefaultSchema()
      .withUser("user").password(passwordEncoder().encode("password")).roles("USER")
      .and()
      .withUser("admin").password(passwordEncoder().encode("password")).roles("USER", "ADMIN");
}

Of course, with both the above examples, we also need to define the PasswordEncoder bean as outlined in Section 3.

9. Conclusion

In this quick tutorial, we went over the basics of Java Configuration for Spring Security and focused on the code samples that illustrate the simplest configuration scenarios.

Course – LSS (cat=Security/Spring Security)

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security:

>> CHECK OUT THE COURSE
res – Security (video) (cat=Security/Spring Security)
Comments are closed on this article!