When would you prefer @Secured or @RolesAllowed over @PreAuthorize?
answer
- static role-only -> @Secured/@RolesAllowed
- need args/SpEL/AND -> @PreAuthorize
- @RolesAllowed = portable JSR-250
- @Secured OR-only, no SpEL
- same enforcement strength either way
basics
~20 sUse @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.
solid answer
~40 s@Secured and @RolesAllowed express one thing well: 'user must have one of these roles.' They win when the rule is a static any-of-roles check because a bare annotation is easier to read and can't harbor a SpEL typo that silently evaluates to something unintended. @RolesAllowed additionally is a JSR-250 Java standard, so it's portable and framework-neutral — attractive if you want to avoid Spring-specific annotations. Prefer @PreAuthorize the moment you need expressiveness: parameter-aware rules (hasRole('ADMIN') or #userId == authentication.name), AND logic, hasPermission, calling a @Bean-backed authorization service, or pre-invocation checks that inspect arguments. @PostAuthorize/filtering are also SpEL-only. The pragmatic guidance many teams follow: enable prePostEnabled and use @PreAuthorize everywhere for consistency, reserving @RolesAllowed for trivial gates where its clarity/portability pays off.
go deeper
Rule of thumb: simple role check = @RolesAllowed; anything with a condition = @PreAuthorize.
Explain the SpEL/argument boundary and OR-only limitation of @Secured/@RolesAllowed.
Weigh portability, SpEL-typo risk, and team consistency; note identical enforcement strength.
Set a codebase convention and justify it; account for the SS6 AuthorizationManager migration.
## The decision framework All three annotations resolve to an `AuthorizationManager` under the hood, so the choice is about **expressiveness vs simplicity/portability**, not capability tiers of enforcement. ### Prefer @Secured / @RolesAllowed when 1. **The rule is purely static role membership** — 'must be ADMIN', 'must be ADMIN or AUDITOR'. A plain annotation reads cleanly and there's no SpEL string to get wrong. 2. **You want no SpEL surface area.** A SpEL typo like `@PreAuthorize("hasRole('ADMN')")` compiles fine and fails at runtime; even worse, a malformed expression can be hard to spot in review. Role-name annotations are simpler to audit. 3. **Portability / standards (specifically @RolesAllowed).** It's JSR-250 (`jakarta.annotation.security`), independent of Spring. If code might run in another Jakarta EE stack, or you have an org policy to prefer standard annotations, @RolesAllowed is the neutral choice. @Secured is Spring-specific and largely a legacy holdover, so between the two, @RolesAllowed is usually preferred for new code. 4. **@Secured only: matching arbitrary authority strings** (e.g. `SCOPE_read`) without role semantics. ### Prefer @PreAuthorize when you need any of - **SpEL / method arguments**: `@PreAuthorize("#account.owner == authentication.name")`. - **Combining conditions**: `hasRole('ADMIN') and #amount < 10000`. - **Custom permission logic**: `hasPermission(#doc, 'WRITE')` via a `PermissionEvaluator`, or calling a bean: `@authz.canEdit(#id)`. - **AND across roles** (impossible with @Secured/@RolesAllowed, which are OR-only). - **Post-invocation / filtering**: `@PostAuthorize`, `@PreFilter`, `@PostFilter` — SpEL-only, no @Secured equivalent. ## Important non-differences - **Security strength is identical** — all go through the same authorization pipeline. Choosing @Secured over @PreAuthorize does not make an endpoint 'more secure.' - All three are bypassed by internal self-invocation and (by default) only advise `public` methods. ## Common team conventions - **All-@PreAuthorize** for uniformity — one mental model, and you never have to migrate a role check when it later needs an argument. - **@RolesAllowed for simple gates, @PreAuthorize for complex ones** — leverages the terseness where it's safe. Both are defensible; the anti-pattern is scattering all three arbitrarily, which multiplies the ways a prefix or SpEL mistake can slip in. ## Migration note Spring Security 6 replaced the old `@EnableGlobalMethodSecurity` and the voter/`AccessDecisionManager` model with `@EnableMethodSecurity` and `AuthorizationManager`. Under the new model @PreAuthorize is fully capable and recommended by Spring for most cases, but @Secured/@RolesAllowed remain supported for the simple-role scenario.
- Between @Secured and @RolesAllowed, which do you pick for new code and why?@RolesAllowed — it's a JSR-250 standard (portable, framework-neutral), its no-prefix naming matches hasRole, and it avoids @Secured's drop-the-ROLE_-prefix trap. @Secured is mainly a legacy Spring annotation.
- Does using @PreAuthorize instead of @Secured make a method more secure?No — they enforce through the same authorization pipeline. @PreAuthorize is only more expressive, not stronger. Security equivalence for identical rules.
saying these in an interview costs you the question
- Claiming @PreAuthorize is 'more secure' than @Secured
- Trying to express AND-of-roles with @Secured/@RolesAllowed
- Thinking @Secured/@RolesAllowed can read method arguments