Information Security 9 min read

Custom Authorization Annotations in Spring Security: Design, Implementation, and Usage

This article explores how to create and use custom authorization annotations in Spring Security to achieve more flexible, expressive, and maintainable permission checks, covering the basics of Spring Security, advantages of custom annotations, step‑by‑step implementation, and additional use‑case scenarios.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Custom Authorization Annotations in Spring Security: Design, Implementation, and Usage

1. Introduction

In Spring Security, authorization is a crucial security mechanism, and the @PreAuthorize annotation is a common way to enforce it; however, real‑world applications often require more flexible and maintainable authorization solutions.

This article discusses how to optimize Spring Security's authorization mechanism by creating custom authorization annotations that better match business requirements, improve code readability, and enhance maintainability.

2. Spring Security Basics

Before diving into custom annotations, we briefly review the core concepts of Spring Security and the usage of the @PreAuthorize annotation.

2.1 Overview of Spring Security

Spring Security is a powerful and flexible framework that protects resources in Spring applications, providing authentication and authorization features for both web and non‑web environments.

2.2 @PreAuthorize Annotation

The @PreAuthorize annotation allows permission checks before method execution. Example usage:

@PreAuthorize("hasRole('ROLE_ADMIN')")
public void adminOperation() {
    // Execute operation that requires admin role
}

The above code permits only users with the ROLE_ADMIN role to invoke adminOperation . Although flexible, developers may seek more intuitive and maintainable alternatives.

3. Advantages of Custom Authorization Annotations

Custom annotations are built on top of Spring Security to address specific business scenarios, offering several benefits over plain @PreAuthorize :

3.1 clearer business semantics

By naming annotations according to business intent, code becomes more expressive. For example, a @VipAccess annotation can denote operations restricted to VIP users.

@VipAccess
public void vipOperation() {
    // Execute operation that requires VIP permission
}

3.2 parameterized and flexible checks

Custom annotations can accept parameters, allowing dynamic permission decisions based on method arguments or other context, which is more flexible than static @PreAuthorize expressions.

@CustomPermission(role = "ROLE_USER", level = 3)
public void customOperation() {
    // Execute operation that requires a specific permission level
}

3.3 improved maintainability

Encapsulating authorization logic inside custom annotations separates it from business code, making future adjustments easier—only the annotation implementation needs to change.

4. Implementing a Custom Authorization Annotation

We demonstrate a concrete example: an annotation that allows method execution only during office hours, named @AccessDuringOfficeHours .

4.1 Create the custom annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessDuringOfficeHours {}

This defines the AccessDuringOfficeHours annotation applicable to methods and classes.

4.2 Implement the authorization logic

import org.springframework.security.access.prepost.PreAuthorize;
import java.lang.annotation.Annotation;
import java.time.LocalTime;

public class AccessDuringOfficeHoursSecurityExpressionRoot extends CustomSecurityExpressionRoot {

    public AccessDuringOfficeHoursSecurityExpressionRoot(Authentication authentication) {
        super(authentication);
    }

    public boolean hasAccessDuringOfficeHours() {
        LocalTime now = LocalTime.now();
        return now.isAfter(LocalTime.of(9, 0)) && now.isBefore(LocalTime.of(18, 0));
    }
}

The class extends CustomSecurityExpressionRoot and provides a method that checks whether the current time falls between 09:00 and 18:00.

4.3 Register the annotation and expression handler

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;

@Configuration
public class SecurityConfig {

    @Autowired
    private CustomPermissionEvaluator customPermissionEvaluator;

    @Bean
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(customPermissionEvaluator);
        expressionHandler.setExpressionParser(new DefaultSpelExpressionParser());
        return expressionHandler;
    }
}

The configuration registers the custom expression root with Spring Security.

4.4 Use the custom annotation

@AccessDuringOfficeHours
public void officeHourOperation() {
    // Execute logic that is allowed only during office hours
}

The officeHourOperation method can be invoked only when the current time is within the defined office‑hour window.

5. Extensions: Other Custom Annotation Scenarios

Beyond the office‑hour example, custom annotations can address many other requirements, such as:

Specific user‑group access: @UserGroupAccess restricts access to members of a particular group.

Valid request source: @ValidRequestSource permits only requests from trusted origins.

Expired access: @AccessExpired allows access only before or after a certain deadline.

These annotations make business rules explicit, resulting in clearer and more maintainable code.

6. Conclusion

By introducing custom authorization annotations, Spring Security can provide more expressive, flexible, and maintainable permission checks that align closely with business needs, improving both code readability and security posture.

In real projects, developers can create additional custom annotations tailored to specific scenarios, further enhancing system security and developer productivity.

JavaCustom AnnotationAuthorizationbackend securitySpring Security
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.