When building secure applications, itβs not just about securing endpointsβyou often need to protect individual methods too. Spring Security provides powerful tools to implement method-level security, primarily using the annotations @PreAuthorize, @PostAuthorize, and @Secured. Weβll walk through how to enable and use Method-Level Security with @PreAuthorize and @Secured in Spring Boot application using the package com.kscodes.springboot.security.
In this tutorial, weβll focus on the two most commonly used annotations in Spring Boot applications:
@PreAuthorize@Secured

π What is Method-Level Security?
Method-level security allows you to apply access restrictions directly on methods in your codebase, usually in service or controller layers.
This means users will only execute a method if they meet certain authentication or role requirements.
βοΈ Enable Method-Level Security
To begin using @PreAuthorize or @Secured, you need to enable method security in your Spring Boot configuration class.
β
Add to SecurityConfig.java
package com.kscodes.springboot.security.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@Configuration
@EnableMethodSecurity(
securedEnabled = true, // Enables @Secured
prePostEnabled = true // Enables @PreAuthorize, @PostAuthorize
)
public class SecurityConfig {
// Additional security config (like filterChain) can go here
}
π Using @Secured
The @Secured annotation is simple and works well for role-based access control (RBAC).
π― Example: Service Layer
package com.kscodes.springboot.security.service;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;
@Service
public class AdminService {
@Secured("ROLE_ADMIN")
public String getAdminDashboard() {
return "Admin dashboard data.";
}
@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
public String getReports() {
return "Accessing reports for admins and managers.";
}
}
β
Note: Roles must be prefixed with "ROLE_". Spring Security automatically adds this prefix to authorities unless you override it.
π§ Using @PreAuthorize
@PreAuthorize supports SpEL (Spring Expression Language) and gives you more flexibility.
π― Example: Controller with Conditions
package com.kscodes.springboot.security.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/user")
public class UserController {
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin-data")
public String getAdminData() {
return "Only accessible by ADMIN role.";
}
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@GetMapping("/common-data")
public String getCommonData() {
return "Accessible by USER and ADMIN roles.";
}
@PreAuthorize("#username == authentication.name")
@GetMapping("/profile/{username}")
public String getUserProfile(@PathVariable String username) {
return "Profile data for user: " + username;
}
}
π‘ Bonus: Method with Custom Condition
@PreAuthorize("hasAuthority('UPDATE_PRIVILEGE') and #id == authentication.principal.id")
public void updateUser(long id) {
// Only if user has the update privilege and owns the ID
}
π§ͺ SecurityContext Test Example
When writing tests or debugging method-level security, you can mock authentication like this:
@WithMockUser(roles = "ADMIN")
@Test
void testAdminOnlyMethod() {
String result = adminService.getAdminDashboard();
assertEquals("Admin dashboard data.", result);
}
βοΈ Comparison: @Secured vs @PreAuthorize
| Feature | @Secured | @PreAuthorize |
|---|---|---|
| Role prefix required | β
Yes (ROLE_) | β Optional (can use hasRole or hasAuthority) |
| Supports SpEL | β No | β Yes |
| Multiple roles | β With array | β
With hasAnyRole() |
| Fine-grained logic | β | β (e.g. match usernames, attributes) |
β Summary
- Method-Level Security with @PreAuthorize and @Secured gives precise access control in Spring Boot applications.
- Use
@Securedfor simple role-based rules. - Use
@PreAuthorizefor complex, conditional logic using Spring Expression Language. - Donβt forget to annotate your config with
@EnableMethodSecurity.