🌱 Spring Boot Q23 / 56

How does Spring Boot integrate with Spring Security?

AI-Powered Answer ✓ Answered

Spring Boot dramatically simplifies the integration and configuration of Spring Security, making it easier to add robust authentication and authorization to applications. It achieves this through auto-configuration, sensible defaults, and dedicated starter dependencies, significantly reducing the amount of boilerplate code required.

1. Starter Dependencies

The primary mechanism for integrating Spring Security with Spring Boot is the spring-boot-starter-security dependency. Adding this single dependency to your project brings in all necessary Spring Security modules and triggers Spring Boot's auto-configuration.

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
gradle
implementation 'org.springframework.boot:spring-boot-starter-security'

2. Auto-Configuration and Default Behavior

Once the security starter is present, Spring Boot automatically configures a default security setup. This includes:

  • Default Login Page: A basic form-based login page is automatically generated and secured for all requests.
  • In-memory User: A default user (user) with a randomly generated password is created at startup. This password is printed to the console/logs.
  • Basic Authentication: For non-browser clients (e.g., REST APIs), HTTP Basic authentication is enabled by default.
  • CSRF Protection: Cross-Site Request Forgery protection is enabled by default for state-changing HTTP methods (POST, PUT, DELETE).
  • Session Management: Default session management is configured.

This out-of-the-box configuration allows developers to quickly get a secured application running without writing any security-specific code, providing immediate protection.

3. Customizing Security Configuration

While the defaults are useful for quick starts, real-world applications require customization. Spring Boot allows this by letting developers define their own SecurityFilterChain bean or extend WebSecurityConfigurerAdapter (though SecurityFilterChain is the modern and recommended approach since Spring Security 5.7+). By defining custom security configurations, developers can:

  • Define custom authentication providers (e.g., JDBC, LDAP, OAuth2).
  • Configure specific authorization rules for different URLs (antMatchers, requestMatchers).
  • Disable or configure CSRF protection.
  • Integrate with OAuth2, JWT, or other token-based authentication mechanisms.
  • Customize the login/logout process and pages.

Here's an example of a basic custom SecurityFilterChain configuration:

java
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.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/", "/home", "/public").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .permitAll()
            )
            .logout(logout -> logout.permitAll());
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

4. Externalizing Security Properties

Spring Boot also allows basic security properties to be configured via application.properties or application.yml. For instance, you can define a default in-memory user directly in the properties file without writing Java code:

properties
spring.security.user.name=admin
spring.security.user.password=mysecretpassword
spring.security.user.roles=USER,ADMIN

5. Method-Level Security

For fine-grained authorization, Spring Boot supports Spring Security's method-level security. By enabling @EnableMethodSecurity (or @EnableGlobalMethodSecurity for older versions) and using annotations like @PreAuthorize, @PostAuthorize, @Secured, or @RolesAllowed, you can secure individual methods based on user roles or expressions.

java
@RestController
@RequestMapping("/api")
@EnableMethodSecurity // Or @EnableGlobalMethodSecurity
public class MyController {

    @GetMapping("/admin-data")
    @PreAuthorize("hasRole('ADMIN')")
    public String getAdminData() {
        return "This is sensitive admin data.";
    }

    @GetMapping("/user-data")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public String getUserData() {
        return "This is user data.";
    }
}