How to Use @PreAuthorize in Spring Boot for Method Security
Use
@PreAuthorize in Spring Boot by enabling method security with @EnableMethodSecurity and annotating your service methods with expressions like @PreAuthorize("hasRole('ROLE_ADMIN')"). This restricts method access based on user roles or permissions before the method runs.Syntax
The @PreAuthorize annotation is placed above a method to define a security expression that must be true for the method to execute. It uses Spring Expression Language (SpEL) to check roles, permissions, or custom conditions.
@PreAuthorize("expression"): The expression defines the access rule.- Common expressions include
hasRole('ROLE_NAME'),hasAuthority('AUTHORITY'), andprincipal.username == #username. - Enable method security in your configuration with
@EnableMethodSecurity.
java
@EnableMethodSecurity public class SecurityConfig { // Security configuration here } @Service public class MyService { @PreAuthorize("hasRole('ROLE_ADMIN')") public void adminOnlyMethod() { // method logic } }
Example
This example shows a Spring Boot service with a method secured by @PreAuthorize to allow only users with the ADMIN role to access it. The security configuration enables method security.
java
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.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.stereotype.Service; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } @Configuration @EnableWebSecurity @EnableMethodSecurity class SecurityConfig { public UserDetailsService userDetailsService() { var user = User.withDefaultPasswordEncoder() .username("admin") .password("password") .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(user); } } @Service class MyService { @PreAuthorize("hasRole('ROLE_ADMIN')") public String adminOnlyAction() { return "Access granted to admin method."; } }
Output
Access granted to admin method.
Common Pitfalls
- Not enabling method security with
@EnableMethodSecuritycauses@PreAuthorizeto be ignored. - Using
hasRole('ADMIN')requires the role to be prefixed withROLE_internally, so the actual role should beROLE_ADMIN. - Placing
@PreAuthorizeon private methods or methods called internally within the same class will not trigger security checks. - Incorrect SpEL syntax or missing quotes can cause runtime errors.
java
/* Wrong: Missing @EnableMethodSecurity disables @PreAuthorize */ @Configuration class WrongConfig { // No @EnableMethodSecurity here } /* Right: Enable method security */ @Configuration @EnableMethodSecurity class RightConfig { // Correct setup }
Quick Reference
| Expression | Description | Example |
|---|---|---|
| hasRole('ROLE_NAME') | Checks if user has a specific role | @PreAuthorize("hasRole('ROLE_ADMIN')") |
| hasAuthority('AUTHORITY') | Checks if user has a specific authority | @PreAuthorize("hasAuthority('WRITE_PRIVILEGE')") |
| principal.username == #username | Checks if the authenticated user's username matches method argument | @PreAuthorize("principal.username == #username") |
| permitAll() | Allows all users to access | @PreAuthorize("permitAll()") |
| denyAll() | Denies all users access | @PreAuthorize("denyAll()") |
Key Takeaways
Always enable method security with @EnableMethodSecurity to activate @PreAuthorize.
@PreAuthorize uses Spring Expression Language to define access rules before method execution.
Roles in hasRole() must be prefixed with ROLE_ internally, e.g., hasRole('ADMIN') checks for ROLE_ADMIN.
Security checks do not apply to private methods or internal calls within the same class.
Use clear and correct SpEL syntax to avoid runtime errors.