0
0
SpringbootHow-ToBeginner · 4 min read

Method Level Security in Spring Boot: How to Use It

To use method level security in Spring Boot, enable it by adding @EnableMethodSecurity to your configuration class. Then, secure methods by annotating them with security annotations like @PreAuthorize or @PostAuthorize to control access based on roles or permissions.
📐

Syntax

Enable method level security by adding @EnableMethodSecurity on a configuration class. Use annotations like @PreAuthorize before methods to specify access rules.

  • @EnableMethodSecurity: Activates method security processing.
  • @PreAuthorize("expression"): Checks the expression before method execution.
  • @PostAuthorize("expression"): Checks the expression after method execution.
  • @Secured({"ROLE_NAME"}): Specifies roles allowed to invoke the method.
java
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;

@Configuration
@EnableMethodSecurity
public class SecurityConfig {
  // Security configuration here
}

// Example usage in a service
import org.springframework.security.access.prepost.PreAuthorize;

public class MyService {

  @PreAuthorize("hasRole('ADMIN')")
  public void adminOnlyMethod() {
    // method logic
  }

  @PreAuthorize("hasAuthority('read')")
  public void readMethod() {
    // method logic
  }
}
💻

Example

This example shows a Spring Boot application with method level security enabled. The adminOnlyMethod can only be called by users with the ADMIN role.

java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@SpringBootApplication
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @Configuration
  @EnableMethodSecurity
  static class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
      http
        .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
        .httpBasic();
      return http.build();
    }

    @Bean
    public UserDetailsService users() {
      UserDetails user = User.builder()
        .username("user")
        .password(passwordEncoder().encode("password"))
        .roles("USER")
        .build();
      UserDetails admin = User.builder()
        .username("admin")
        .password(passwordEncoder().encode("password"))
        .roles("ADMIN")
        .build();
      return new InMemoryUserDetailsManager(user, admin);
    }

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

  @Service
  public static class MyService {

    @PreAuthorize("hasRole('ADMIN')")
    public String adminOnlyMethod() {
      return "Access granted to admin method.";
    }

    @PreAuthorize("hasRole('USER')")
    public String userMethod() {
      return "Access granted to user method.";
    }
  }
}
Output
When logged in as 'admin' and calling adminOnlyMethod(): "Access granted to admin method." When logged in as 'user' and calling adminOnlyMethod(): Access denied error
⚠️

Common Pitfalls

  • Forgetting to add @EnableMethodSecurity disables method security annotations.
  • Using @PreAuthorize without enabling prePostEnabled in older Spring versions (before 6.0).
  • Not matching roles exactly, e.g., hasRole('ADMIN') expects role name without ROLE_ prefix.
  • Trying to secure private methods; Spring proxies only public methods by default.
java
/* Wrong: Missing @EnableMethodSecurity disables method security */
@Configuration
public class SecurityConfig {
  // no method security enabled
}

/* Right: Enable method security */
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
  // method security enabled
}
📊

Quick Reference

Use this quick reference to remember key annotations and their purpose:

AnnotationPurpose
@EnableMethodSecurityEnables method level security processing
@PreAuthorize("expression")Checks authorization before method execution
@PostAuthorize("expression")Checks authorization after method execution
@Secured({"ROLE_NAME"})Restricts method access to specified roles
@RolesAllowed({"ROLE_NAME"})Java EE standard for role-based access control

Key Takeaways

Add @EnableMethodSecurity to your configuration to activate method level security.
Use @PreAuthorize to restrict method access based on roles or permissions.
Roles in hasRole() should be specified without the ROLE_ prefix.
Method security works on public methods by default due to Spring proxies.
Test security by logging in with different users and calling secured methods.