Spring Security Method-Level Security Using @PreAuthorize, @PostAuthorize, and @Secured

Introduction :

Security is one of the most important aspects of enterprise applications. In many real-world projects, different users have different permissions. For example, an Admin can create users, a Manager can approve requests, and a Customer can only view their own data.

In our previous article, we learned about Role-Based Access Control (RBAC) in Spring Security. However, securing entire URLs is not always enough. Sometimes, we need to secure specific methods inside controllers or services. This is where Method-Level Security comes into the picture.

In this article, we will learn how to use @PreAuthorize, @PostAuthorize, and @Secured annotations to implement fine-grained access control in Spring Boot applications.



What is Method-Level Security?

Method-Level Security allows developers to control access to individual methods based on roles, permissions, or custom conditions.

Instead of securing an entire endpoint, we can secure specific methods.

For example:

  • Only ADMIN can create users.

  • Only MANAGER can approve loans.

  • Customers can view only their own account details.

This approach provides better security and flexibility.


Enabling Method Security

Before using method security annotations, we must enable it in our Spring Security configuration.

@Configuration
@EnableMethodSecurity
public class SecurityConfig {
}

The @EnableMethodSecurity annotation enables support for:

  • @PreAuthorize

  • @PostAuthorize

  • @Secured


Using @Secured Annotation

The @Secured annotation is the simplest way to restrict access based on roles.

Example

@Secured("ROLE_ADMIN")
public void createUser() {
    System.out.println("User Created");
}

Only users with the ADMIN role can access this method.

Real-Time Example

In an HR Management System:

@Secured("ROLE_HR")
public void approveLeave() {
}

Only HR personnel can approve employee leave requests.

Limitation

@Secured only supports role-based checks and does not support complex expressions.


Using @PreAuthorize Annotation

The @PreAuthorize annotation performs authorization before method execution.

Example

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser() {
    System.out.println("User Deleted");
}

The method executes only if the user has the ADMIN role.

Multiple Roles Example

@PreAuthorize("hasAnyRole('ADMIN','MANAGER')")
public void viewReports() {
}

Both ADMIN and MANAGER can access this method.


Real-Time Banking Example

Suppose we have a banking application.

@Service
public class LoanService {

    @PreAuthorize("hasRole('MANAGER')")
    public String approveLoan() {
        return "Loan Approved";
    }
}

Only Managers can approve loans.

If a Customer tries to access the method, Spring Security throws an Access Denied exception.


Using Permissions with @PreAuthorize

We can also check permissions.

@PreAuthorize("hasAuthority('USER_READ')")
public List<User> getUsers() {
    return userRepository.findAll();
}

This is useful when applications use permissions instead of roles.

Examples:

  • USER_READ

  • USER_WRITE

  • USER_DELETE


Using @PostAuthorize Annotation

The @PostAuthorize annotation performs authorization after method execution.

This is useful when authorization depends on the returned object.

Example

@PostAuthorize("returnObject.username == authentication.name")
public User getUser(Long id) {
    return userRepository.findById(id).orElse(null);
}

How It Works

  1. Method executes first.

  2. User data is returned.

  3. Spring Security checks whether the logged-in user matches the returned username.

  4. Access is granted or denied.


Real-Time Customer Account Example

@PostAuthorize("returnObject.owner == authentication.name")
public Account getAccount(Long accountId) {
    return accountRepository.findById(accountId).orElse(null);
}

This ensures customers can only view their own accounts.

Even if they know another account ID, access will be denied.


Difference Between @Secured and @PreAuthorize



In modern Spring Boot applications, @PreAuthorize is generally preferred because of its flexibility.


Common Mistakes

1. Forgetting @EnableMethodSecurity

Without this annotation, method security will not work.

@EnableMethodSecurity

2. Role Prefix Issues

Spring Security expects roles in the format:

ROLE_ADMIN
ROLE_USER

Using incorrect role names can cause authorization failures.

3. Using @PostAuthorize for Heavy Operations

Since authorization happens after method execution, unnecessary processing may occur before access is denied.

Use it only when required.


Interview Questions

1. What is Method-Level Security in Spring Security?

Method-Level Security restricts access to specific methods using annotations such as @PreAuthorize, @PostAuthorize, and @Secured.

2. What is the difference between @PreAuthorize and @PostAuthorize?

  • @PreAuthorize checks access before method execution.

  • @PostAuthorize checks access after method execution.

3. Which annotation is preferred in modern applications?

@PreAuthorize is preferred because it supports powerful SpEL expressions and complex authorization rules.

4. What is the purpose of @EnableMethodSecurity?

It enables method-level security annotations in Spring Boot applications.

5. Can @Secured perform authority checks?

No. It only supports role-based authorization.


Conclusion :

Method-Level Security provides fine-grained control over application access and is widely used in enterprise Spring Boot applications. While @Secured is suitable for simple role-based checks, @PreAuthorize offers more flexibility and is commonly used in modern projects. @PostAuthorize becomes useful when authorization depends on the method's returned data.

By properly using these annotations, developers can build secure and scalable applications while ensuring that users access only the resources they are authorized to use.

In the next article, we'll explore OAuth 2.0 Authentication in Spring Security and learn how modern applications use authorization servers, access tokens, and secure API access mechanisms.

Comments

Popular posts from this blog

React Basics – How to Create Component

How to Build REST API using Spring Boot (Step-by-Step Guide)

Spring Boot @RequestParam Annotation Explained with Real-Time Examples