Role Based Access: @PreAuthorize
URL rules secure the gates. @PreAuthorize secures the individual rooms.
The Hospital Operation Theater Analogy:
In a hospital, the main gate security checks if you are a valid doctor or patient (URL Security). But when you try to perform a surgery in the Operation Theater, a second check happens: Are you a Surgeon? A nurse is allowed in the hospital, but not allowed to perform surgery.
In Spring Boot, @PreAuthorize is that second check. It happens right before the Java method executes. It checks the user’s role before allowing the code to run.
- @EnableMethodSecurity: In Spring Security 6, this replaces
@EnableGlobalMethodSecurity. It turns on the engine that reads@PreAuthorizeannotations. - @PreAuthorize("hasRole('ADMIN')"): Places a lock on the method. Only users whose JWT contains the
ADMINrole can enter. - Roles vs Authorities: In Spring Security, a Role is prefixed with
ROLE_(e.g.,ROLE_ADMIN). When usinghasRole('ADMIN'), Spring automatically adds theROLE_prefix.
First, enable method security on your main class.
package com.devinhyderabad;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@SpringBootApplication
@EnableMethodSecurity // Replaces @EnableGlobalMethodSecurity in SB3
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}Now, apply it to your controller methods.
package com.devinhyderabad;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/orders")
public class OrderController {
// 1. Anyone with a valid JWT (USER or ADMIN) can access this
@GetMapping("/{id}")
public String getOrder(@PathVariable Long id) {
return "Order details for " + id;
}
// 2. ONLY users with the ADMIN role can delete
@DeleteMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
public String deleteOrder(@PathVariable Long id) {
return "Order " + id + " deleted by Admin!";
}
// 3. Multiple roles allowed
@PutMapping("/{id}")
@PreAuthorize("hasAnyRole('ADMIN', 'MANAGER')")
public String updateOrder(@PathVariable Long id) {
return "Order updated!";
}
}If a regular USER tries to call DELETE /api/orders/1, Spring Security throws an AccessDeniedException (403 Forbidden) before the deleteOrder method even executes.
The setup is simple:
- @EnableMethodSecurity: Enables Spring Security’s annotation-based security. This is a one-time setup on your
@SpringBootApplicationclass. - @PreAuthorize with SpEL: The annotation accepts Spring Expression Language (SpEL).
hasRole('ADMIN')checks if the authenticated user has theROLE_ADMINauthority. - hasAnyRole: For scenarios where multiple roles should have access (e.g., both ADMIN and MANAGER can update orders).
Note: For @PreAuthorize to work with roles, your JwtAuthenticationFilter must extract roles from the JWT and pass them as GrantedAuthority objects into the UsernamePasswordAuthenticationToken.
Interview Question: “What is the difference between @Secured and @PreAuthorize?”
Answer: @Secured("ROLE_ADMIN") is older and only supports checking simple roles. @PreAuthorize("hasRole('ADMIN') and #order.owner == authentication.name") uses Spring Expression Language (SpEL). It is much more powerful because you can write complex logic, like “Allow access only if the user is the owner of this order”.
Enterprise Note: To make @PreAuthorize work with roles, your JwtAuthenticationFilter must extract the roles from the JWT and pass them as GrantedAuthority objects into the UsernamePasswordAuthenticationToken. If your filter only sets the username and no authorities, hasRole('ADMIN') will always fail.
Key Takeaways
- ✅ @PreAuthorize provides method-level security beyond basic URL rules
- ✅ @EnableMethodSecurity replaces @EnableGlobalMethodSecurity in Spring Security 6
- ✅ Roles get auto-prefixed with ROLE_ when using hasRole()
- ✅ SpEL in @PreAuthorize supports complex conditions (owner checks, etc.)
- ✅ JwtAuthenticationFilter must pass GrantedAuthority objects for role checks
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login