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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
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
1 2 3 4 5 6 7 |
@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:
1 2 3 4 5 6 7 8 9 |
@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
@Secured
for simple role-based rules. - Use
@PreAuthorize
for complex, conditional logic using Spring Expression Language. - Don’t forget to annotate your config with
@EnableMethodSecurity
.