Spring Security method level security PreAuthorize Secured — Complete Guide
A practical, in-depth guide to Spring Security method level security PreAuthorize Secured with examples.
INTRO
Every production‑grade Spring Boot service eventually hits the point where you need to protect who can call what. Relying solely on URL‑based filters leaves a dangerous blind spot: a malicious client can bypass the front‑door by invoking a service bean directly, or a teammate can accidentally expose a critical operation through a new endpoint. The result? Sensitive data leaks, unauthorized state changes, and a nightmare when you try to audit who did what.
Method‑level security closes that gap by moving the access decision right to the business logic. With annotations like @PreAuthorize and @Secured, you declare intent next to the code that matters, and Spring’s expression language lets you compose complex rules without scattering if‑else checks throughout the codebase. The trade‑off is a bit of configuration and a learning curve around SpEL, but the payoff is a clean, declarative security model that scales with your domain.
If you’ve ever wrestled with “who can delete a user?” or “why does my admin endpoint still reject a manager token?”, this guide will give you a concrete, end‑to‑end recipe for getting method security right the first time.
WHAT YOU'LL LEARN
-
The difference between
@PreAuthorizeand@Secured– when to pick one over the other and how they interact with Spring’sMethodSecurityExpressionHandler. -
Setting up global method security – the minimal
@EnableGlobalMethodSecurityflags you need, and how to avoid the common pitfall of forgetting to enable proxy‑based security. -
Writing expressive SpEL expressions – from simple role checks (
hasRole('ADMIN')) to dynamic permission lookups (@permissionService.hasAccess(#id, authentication)). -
Integrating custom permission evaluators – plug in your own
PermissionEvaluatororMethodSecurityExpressionRootto enforce domain‑specific rules without polluting controllers. -
Testing method security – unit‑test strategies with
@WithMockUser,@WithSecurityContext, and the Spring Test Security module to guarantee your annotations behave as expected. -
Production hardening tips – caching decisions, handling
AccessDeniedExceptionglobally, and avoiding proxy‑target class pitfalls in AOP‑heavy applications.
A SHORT CODE SNIPPET
@Service
public class DocumentService {
// Only users with ROLE_EDITOR or the owner of the document can update it
@PreAuthorize("hasRole('EDITOR') or @docPermission.checkOwner(#docId, authentication)")
public Document updateDocument(Long docId, DocumentDto dto) {
Document doc = repository.findById(docId)
.orElseThrow(() -> new NotFoundException());
// business logic …
return repository.save(doc);
}
}
In this tiny fragment the security rule lives right next to the method signature. The custom bean docPermission encapsulates the “owner” check, keeping the expression readable while still leveraging full Spring DI.
KEY TAKEAWAYS
- Method‑level annotations give you defense in depth by protecting the service layer, not just the web layer.
-
@PreAuthorizeoffers full SpEL power;@Securedis a lightweight alternative for simple role checks. - A custom
PermissionEvaluatoror expression root lets you express domain concepts (ownership, hierarchy, time‑based access) without leaking them into controllers. - Proper testing and proxy configuration are essential; a mis‑configured
@EnableGlobalMethodSecuritysilently disables all your annotations.
👉 Read the complete guide with step-by-step examples, common mistakes, and production tips:
Spring Security method level security PreAuthorize Secured — Complete Guide
Top comments (0)