๐ @PolicyScope
Annotation System
This document explains how to define, use, and enforce repeatable @PolicyScope
annotations in a Spring Boot application using Aspect-Oriented Programming (AOP).
๐งฉ Purpose
@PolicyScope
is a repeatable annotation used to declare one or more logical access scopes on a method. These scopes can be inspected at runtime to enforce access control policies or log activity.
โ Annotation Definitions
import java.lang.annotation.*;
@Repeatable(PolicyScopes.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface PolicyScope {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface PolicyScopes {
PolicyScope[] value();
}
๐
@PolicyScope
is marked@Repeatable
using the container annotation@PolicyScopes
.
๐งช Example Usage
public class UserService {
@PolicyScope("user:read")
@PolicyScope("audit:log")
public void fetchUsers() {
System.out.println("Fetching users...");
}
@PolicyScopes({
@PolicyScope("user:write"),
@PolicyScope("audit:log")
})
public void modifyUsers() {
System.out.println("Modifying users...");
}
}
You may use either:
- Multiple
@PolicyScope
annotations - A single
@PolicyScopes
container - Or both (though redundant)
๐ง Enforcing with Spring AOP
The following aspect intercepts all methods annotated with @PolicyScope
or @PolicyScopes
and enforces the scopes:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class PolicyScopeAspect {
@Around("execution(* *(..)) && (@annotation(PolicyScope) || @annotation(PolicyScopes))")
public Object enforcePolicyScopes(ProceedingJoinPoint joinPoint) throws Throwable {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
PolicyScope[] scopes = method.getAnnotationsByType(PolicyScope.class);
checkPolicy(scopes); // pass all annotations directly
return joinPoint.proceed();
}
private void checkPolicy(PolicyScope[] scopes) {
for (PolicyScope scope : scopes) {
System.out.println("โ
Enforcing policy: " + scope.value());
// Replace this with actual policy enforcement logic
}
}
}
๐ค Example Output
Given this method:
@PolicyScopes({
@PolicyScope("admin:access"),
@PolicyScope("audit:log")
})
public void adminPanel() { ... }
Or this method:
@PolicyScope("admin:access")
@PolicyScope("audit:log")
public void adminPanel() { ... }
Console output:
โ
Enforcing policy: admin:access
โ
Enforcing policy: audit:log