skip to content

Method Security

Authorization at the method rather than the URL: enabling it, @PreAuthorize and @PostAuthorize, the simpler role annotations, collection filtering, and permission evaluators. Interviewers like it because it is where authorization meets domain logic.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

24

What does @EnableMethodSecurity do, and what are its prePostEnabled, securedEnabled, and jsr250Enabled flags?

level: juniorimportance: must knowfreq 70%

answer

  1. @Configuration + @EnableMethodSecurity
  2. prePostEnabled defaults TRUE
  3. securedEnabled = @Secured (role list)
  4. jsr250Enabled = @RolesAllowed/@PermitAll/@DenyAll
  5. AOP proxy — self-invocation bypasses

basics

~10 s

@EnableMethodSecurity turns on security checks on individual methods (not just URLs). prePostEnabled activates @PreAuthorize/@PostAuthorize (on by default), securedEnabled activates @Secured, and jsr250Enabled activates @RolesAllowed. You put it on a @Configuration class.

solid answer

~40 s

@EnableMethodSecurity is the annotation (Spring Security 5.6+) you add to a @Configuration class to enable authorization on individual bean methods rather than only on HTTP requests. It registers AOP interceptors that evaluate security annotations before or after a method runs. Its three flags toggle which annotation families are active: prePostEnabled turns on Spring's @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter (and, importantly, it defaults to true); securedEnabled turns on the legacy role-list @Secured; jsr250Enabled turns on the JSR-250 annotations @RolesAllowed, @PermitAll, @DenyAll. You typically leave prePostEnabled on and only enable the others if your codebase uses those annotation styles. Method security is enforced through Spring AOP proxies, so calls must go through the proxy for the check to fire.

code

java · 16 lines
java
@Configuration
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
public class MethodSecurityConfig { }

@Service
public class AccountService {

    @PreAuthorize("hasRole('ADMIN')")            // prePostEnabled (default true)
    public void closeAccount(String id) { }

    @Secured("ROLE_ADMIN")                        // securedEnabled
    public void freeze(String id) { }

    @RolesAllowed("ADMIN")                        // jsr250Enabled
    public void reopen(String id) { }
}

go deeper

for a junior

Know it enables per-method checks and name the three flags with the annotations each turns on.

for a middle

Explain the defaults (prePostEnabled=true, others false) and that @PreAuthorize is SpEL while @Secured/@RolesAllowed are plain role lists.

for a senior

Explain the AOP-proxy enforcement path and the self-invocation gotcha, and advise which annotation family to standardize on.

for a principal

Discuss migration policy, meta-annotation/templated-expression support, and enabling multiple families safely across a large codebase.

## What it is `@EnableMethodSecurity` is a Spring Security annotation (introduced in **Spring Security 5.6**, GA in 5.8 / Spring Boot 3) that you place on a `@Configuration` class to enable **method-level authorization** — deciding whether a caller may invoke a specific bean method, as opposed to *web* authorization which guards HTTP request paths in the `SecurityFilterChain`. ```java @Configuration @EnableMethodSecurity // prePostEnabled = true by default public class MethodSecurityConfig { } ``` ## How it works under the hood When present, its `@Import(MethodSecuritySelector.class)` pulls in configuration that registers **Spring AOP advisors** (interceptor beans). Each secured bean is wrapped in a **proxy**; when a method annotated for security is called *through that proxy*, the matching interceptor runs an `AuthorizationManager` to grant or deny access, throwing `AccessDeniedException` on denial. ## The three flags - **prePostEnabled** — enables the Spring-native, SpEL-powered annotations: `@PreAuthorize` (check *before* the method), `@PostAuthorize` (check the *return value* after), `@PreFilter` (filter a collection/array *argument*), `@PostFilter` (filter the returned collection). **Unlike the old `@EnableGlobalMethodSecurity`, this flag defaults to `true`.** - **securedEnabled** — enables the legacy `@Secured` annotation, which takes a plain list of role strings, e.g. `@Secured("ROLE_ADMIN")`. No SpEL. Defaults to `false`. - **jsr250Enabled** — enables the Jakarta/JSR-250 standard annotations `@RolesAllowed("ADMIN")`, `@PermitAll`, `@DenyAll`. Defaults to `false`. ```java @EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true) ``` ## Which to use Prefer `@PreAuthorize` (SpEL, can reference method arguments via `#name`, principal, authorities) for anything expressive. Use `@Secured` / `@RolesAllowed` only for simple role checks or to match an existing convention. You can enable more than one family simultaneously; different annotations then apply to different methods. ## Key gotchas - **Proxy self-invocation**: a call from one method of a bean to another method *of the same bean* (`this.other()`) bypasses the proxy, so its security annotation is **not** enforced. Route through an injected reference or split beans. - **Public methods only** by default (Spring AOP CGLIB/JDK proxies can't advise `private`/`final` methods the usual way). - Where you put the annotation still matters: it must be on a **Spring-managed bean**. - Meta-annotations / templated authorization expressions are supported (a big reason it replaced the old annotation).

  • If you only write @EnableMethodSecurity with no arguments, which annotations work?
    Only the pre/post family — @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter — because prePostEnabled defaults to true while securedEnabled and jsr250Enabled default to false.
  • Why might a @PreAuthorize on your method never trigger?
    Common causes: the class isn't a Spring bean, the method is called via self-invocation (this.method()) so it skips the proxy, or the method is private/final and can't be proxied.

saying these in an interview costs you the question

  • Thinking prePostEnabled must be set explicitly (it defaults to true).
  • Believing @Secured supports SpEL expressions (it only takes role name strings).
  • Assuming method security guards URLs — it guards method calls; URL rules live in the SecurityFilterChain.
  • Expecting self-invoked (this.x()) annotated calls to be secured.

context

open as a page

What do @PreAuthorize and @PostAuthorize do, and how do you turn them on in a Spring application?

level: juniorimportance: must knowfreq 78%

basics

~10 s

@PreAuthorize checks a rule before a method runs; @PostAuthorize checks after it returns. You enable them by adding @EnableMethodSecurity to a configuration class. If the rule is false, access is denied with an exception.

open as a page

What are @Secured and @RolesAllowed in Spring Security, and what do they do?

level: juniorimportance: must knowfreq 55%

basics

~10 s

Both are method-level annotations that restrict who can call a method based on their roles. @RolesAllowed is a Java standard (JSR-250); @Secured is Spring's own. You list allowed roles and Spring blocks everyone else.

open as a page

How do you implement and register a custom PermissionEvaluator in Spring Security 6?

level: middleimportance: must knowfreq 55%

basics

~10 s

Implement the PermissionEvaluator interface (its two hasPermission methods) with your own logic, then publish a MethodSecurityExpressionHandler bean, calling setPermissionEvaluator() so @PreAuthorize's hasPermission() uses it.

open as a page

What variables can you reference in @PreAuthorize/@PostAuthorize SpEL — how do you read method arguments, the principal, and the return value?

level: middleimportance: must knowfreq 72%

basics

~20 s

You can reference method arguments by name (or #p0, #p1), the current user via authentication and principal, and — only in @PostAuthorize — the method's result via returnObject. You combine them with helpers like hasRole() and hasAuthority().

open as a page

What is the difference between @Secured and @RolesAllowed regarding the ROLE_ prefix and role naming?

level: middleimportance: must knowfreq 50%

basics

~10 s

@RolesAllowed takes the bare role name ("ADMIN") and Spring adds the ROLE_ prefix. @Secured takes the full authority string, so you must write "ROLE_ADMIN" yourself. Forgetting the prefix on @Secured silently denies access.

open as a page

Why can a @PreAuthorize on a method be silently bypassed when another method in the same class calls it, and how do you fix that?

level: seniorimportance: must knowfreq 68%

basics

~20 s

Method security runs through a proxy that wraps the bean. When one method calls another method on the same object with this, the call never leaves the object, so the proxy is skipped and the @PreAuthorize check doesn't run. Call through the injected bean instead, or move the method to another bean.

open as a page

What does the hasPermission() expression do inside @PreAuthorize, and what backs it?

level: juniorimportance: should knowfreq 45%

basics

~10 s

hasPermission() is a SpEL check you write in @PreAuthorize/@PostAuthorize. It asks 'can this user do X on this object?'. Spring delegates the yes/no answer to a PermissionEvaluator bean you configure.

open as a page

What do @PreFilter and @PostFilter do in Spring Security, and what does filterObject refer to?

level: juniorimportance: should knowfreq 35%

basics

~10 s

They remove elements from a collection based on a security rule. @PreFilter filters a collection method argument before the method runs; @PostFilter filters the collection the method returns. filterObject is each element being tested.

open as a page

Compare @PreAuthorize (prePostEnabled) with @Secured (securedEnabled) and @RolesAllowed (jsr250Enabled): when would you choose each?

level: middleimportance: should knowfreq 55%

basics

~20 s

@PreAuthorize takes a full SpEL expression, so it can check roles, method arguments, and custom logic — the most powerful. @Secured and @RolesAllowed only take plain role-name strings for simple checks. Prefer @PreAuthorize unless you want a standard/simple role list.

open as a page

A @PreAuthorize annotation on a service method is being ignored at runtime. What are the likely causes given how @EnableMethodSecurity works?

level: middleimportance: should knowfreq 50%

basics

~20 s

Method security uses AOP proxies. The check only runs when the call comes through the proxy. Common misses: calling the method from within the same bean (self-invocation), the class isn't a Spring bean, the method is private/final, or you forgot @EnableMethodSecurity / the right flag.

open as a page

What requirement does @PreFilter place on the collection it modifies, and how do you tell it which argument to filter when a method has several collection parameters?

level: middleimportance: should knowfreq 30%

basics

~20 s

@PreFilter removes elements in place, so the collection argument must be mutable — an immutable one (like List.of(...)) throws UnsupportedOperationException. When a method has multiple collection parameters, name the one to filter with the filterTarget attribute.

open as a page

What are the semantics when @Secured or @RolesAllowed list multiple roles, and what can't they express?

level: middleimportance: should knowfreq 38%

basics

~20 s

Multiple listed roles mean OR — having any one of them grants access. Neither annotation can express AND (require several roles at once), negation, or any condition based on method arguments. For those you need @PreAuthorize with SpEL.

open as a page

Why did @EnableMethodSecurity replace @EnableGlobalMethodSecurity, and what changed?

level: seniorimportance: should knowfreq 45%

basics

~20 s

@EnableMethodSecurity (Spring Security 5.6+) replaces the deprecated @EnableGlobalMethodSecurity. It's built on the newer, simpler AuthorizationManager API instead of the old AccessDecisionManager/voter machinery, defaults prePostEnabled to true, and supports meta-annotations and custom SpEL beans more cleanly.

open as a page

How does the spring-security-acl module implement domain-object security, and what are its moving parts?

level: seniorimportance: should knowfreq 35%

basics

~10 s

spring-security-acl stores per-object, per-user permissions in four DB tables. AclPermissionEvaluator (a PermissionEvaluator) looks up an object's ACL via AclService and checks whether the current user's Sid was granted the requested Permission mask.

open as a page

In Spring Security 6, what actually enforces @PreAuthorize at runtime — walk through the interceptor and AuthorizationManager path and how it differs from the old model.

level: seniorimportance: should knowfreq 42%

basics

~20 s

A method interceptor named AuthorizationManagerBeforeMethodInterceptor wraps the bean. Before the method runs it asks an AuthorizationManager (backed by a SpEL expression handler) to decide; if the decision is a deny, it throws AccessDeniedException. This replaces the old voter/AccessDecisionManager stack from @EnableGlobalMethodSecurity.

open as a page

Why can @PostFilter be dangerous for performance and pagination, and how should you handle authorization for large or paged result sets instead?

level: seniorimportance: should knowfreq 25%

basics

~20 s

@PostFilter loads every row first, then discards the forbidden ones in memory — wasteful for big datasets and it breaks pagination (a page of 20 can shrink to fewer, and totals are wrong). Better: filter in the database query itself.

open as a page

How does @PostFilter differ from @PostAuthorize, and which collection types can @PreFilter/@PostFilter actually operate on?

level: seniorimportance: should knowfreq 28%

basics

~10 s

@PostAuthorize makes one keep-or-throw decision on the whole return value (via returnObject); @PostFilter prunes a returned collection element by element (via filterObject), never throwing. Filtering supports Collection, arrays, and Stream — not Map.

open as a page

When would you prefer @Secured or @RolesAllowed over @PreAuthorize?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Use @Secured/@RolesAllowed for simple, static role-only checks — they are terser and less error-prone than a SpEL string. Prefer @RolesAllowed for portability. Switch to @PreAuthorize whenever you need SpEL: method arguments, combined conditions, or custom expressions.

open as a page

When would you choose @PostAuthorize over @PreAuthorize, and what are the risks of guarding a method after it has already executed?

level: principalimportance: should knowfreq 38%

basics

~20 s

Use @PostAuthorize when the decision depends on the object the method returns — for example an ownership check on the loaded entity. The risk is that the method body runs first: any side effects, expensive work, or data loading happen even when access is finally denied, and only the return value is thrown away.

open as a page

How are method-security checks physically applied — how are the interceptors registered and ordered as advisors?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

@EnableMethodSecurity registers a set of AOP advisor beans (pointcut + interceptor pairs), one per annotation type. Spring proxies your secured beans; when a matching method is called, the advisor's interceptor runs an AuthorizationManager to allow or deny. Their run order is fixed by AuthorizationInterceptorsOrder.

open as a page

When would you choose spring-security-acl over a custom PermissionEvaluator or a query-level filter, and what are the pitfalls at scale?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

Use spring-security-acl only when permissions are per-object, admin-managed, and change at runtime (Google-Docs-style sharing). For ownership or role rules, a small custom PermissionEvaluator — or filtering in the SQL query — is simpler and faster.

open as a page

As a technical lead, how would you decide when method-level @PreFilter/@PostFilter is the right authorization mechanism versus enforcing access control elsewhere, and what pitfalls would you call out in review?

level: principalimportance: nice to knowfreq 15%

basics

~20 s

Use @PreFilter/@PostFilter only for small, per-element visibility rules on service methods. Prefer data-layer filtering for large or paged reads, keep authorization out of the persistence path for correctness, and watch for immutable-collection breakage, silent result-shrinking, and proxy/self-invocation gaps.

open as a page

How does Spring Security 6 process @Secured and @RolesAllowed under the hood, and what changed from @EnableGlobalMethodSecurity?

level: principalimportance: nice to knowfreq 25%

basics

~10 s

In Spring Security 6, @EnableMethodSecurity builds AOP interceptors backed by AuthorizationManager beans — SecuredAuthorizationManager for @Secured and Jsr250AuthorizationManager for @RolesAllowed. This replaced the old @EnableGlobalMethodSecurity model that used AccessDecisionManager and voters.

open as a page