DEV Community

Rajesh Mishra
Rajesh Mishra

Posted on Originally published at howtostartprogramming.in

Spring Security method level security PreAuthorize Secured — Complete Guide

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 @PreAuthorize and @Secured – when to pick one over the other and how they interact with Spring’s MethodSecurityExpressionHandler.
  • Setting up global method security – the minimal @EnableGlobalMethodSecurity flags 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 PermissionEvaluator or MethodSecurityExpressionRoot to 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 AccessDeniedException globally, 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);
}
}
Enter fullscreen mode Exit fullscreen mode

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.
  • @PreAuthorize offers full SpEL power; @Secured is a lightweight alternative for simple role checks.
  • A custom PermissionEvaluator or 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 @EnableGlobalMethodSecurity silently 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)