Beyond @PreAuthorize: Complete Guide to Spring Security Annotations with a Spring Boot Demo
This article systematically explains the full set of Spring Security annotations—including @EnableWebSecurity, @EnableMethodSecurity, @Secured, @PreAuthorize, @PostAuthorize, and @RolesAllowed—showing how they work, their differences, and how to apply them in a practical Spring Boot project.
Many developers only use @PreAuthorize for permission control in Spring Boot projects, mistakenly believing the security system is complete. In reality, Spring Security offers a rich annotation ecosystem that enables both method‑level and endpoint security.
Annotation Architecture
Spring Security annotations primarily support method security. The workflow is simple: developers declare permission rules via annotations, and Spring Security automatically enforces them, eliminating the need for custom permission logic.
Project Dependency
To use Spring Security annotations in a Spring Boot project, add the starter dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>This starter provides authentication, authorization, password encoding, a security filter chain, and method‑security support.
@EnableWebSecurity
The annotation enables the web security configuration, activating the filter chain, default authentication mechanisms, and authorization management. A typical configuration class looks like:
//src/main/java/com/icoderoad/config/SecurityConfig.java
package com.icoderoad.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
}@EnableMethodSecurity
To use method‑level annotations such as @PreAuthorize, @PostAuthorize, and @Secured, enable method security:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
}@Secured
@Securedis one of the earliest Spring Security annotations and restricts method access to specific roles. Example:
//src/main/java/com/icoderoad/controller/AdminController.java
package com.icoderoad.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AdminController {
@GetMapping("/admin")
@Secured("ROLE_ADMIN")
public String admin() {
return "Admin access granted";
}
}If the user lacks the required role, Spring returns 403 Forbidden. A limitation of @Secured is that it does not support complex SpEL expressions, which leads many projects to prefer @PreAuthorize.
@PreAuthorize
This is the most powerful method‑level annotation, supporting SpEL expressions. Example:
//src/main/java/com/icoderoad/controller/UserController.java
package com.icoderoad.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
public String getUser(@PathVariable Long id) {
return "User ID: " + id;
}
}Common expressions include hasRole('ADMIN'), hasAuthority('READ'), isAuthenticated(), and permitAll(). A complex example:
@PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id")It allows access to administrators or the owner of the requested data.
@PostAuthorize
Unlike @PreAuthorize, this annotation checks permissions after method execution. Example:
@PostAuthorize("returnObject.username == authentication.name")
public User getProfile(@PathVariable Long id) {
return userService.getUser(id);
}Access succeeds only when the returned object's username matches the authenticated user; otherwise an AccessDeniedException is thrown.
@RolesAllowed
This JSR‑250 standard annotation is similar to @Secured but originates from Java EE. To enable it, configure:
@EnableMethodSecurity(jsr250Enabled = true)Full Spring Security Demo
Project structure:
src/main/java/com/icoderoad
├── config
│ └── SecurityConfig.java
├── controller
│ ├── AdminController.java
│ └── UserController.java
└── service
└── UserService.javaKey configuration:
package com.icoderoad.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
}Sample controller demonstrating various annotations:
@RestController
@RequestMapping("/api")
public class DemoController {
@GetMapping("/public")
public String publicApi() { return "Public API"; }
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin")
public String admin() { return "Admin API"; }
@Secured("ROLE_MANAGER")
@GetMapping("/manager")
public String manager() { return "Manager API"; }
}Best Practices
Recommended strategy separates concerns:
Controller — API permissions
Service — Business permissions
Repository — Data‑access permissionsApplying @PreAuthorize at the service layer prevents bypassing security by calling controller methods directly.
Conclusion
Spring Security’s annotation suite includes @EnableWebSecurity, @EnableMethodSecurity, @Secured, @PreAuthorize, @PostAuthorize, and @RolesAllowed. Combining these with RBAC, JWT/OAuth2, and data‑level controls yields a robust permission system—far beyond writing a single annotation.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
LuTiao Programming
LuTiao Programming is a friendly community offering free programming lessons. We inspire learners to explore new ideas and technologies and quickly acquire job-ready skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
