I\'d like to implement declarative security with Spring/AOP and annotations. As you see in the next code sample I have the Restricted Annotations with the paramter \"allowed
Why don't you just use Spring Security ? It's a brief to implement and use, I don't really see the point in wasting time reinventing the wheel.
Whith Spring AOP if you have a situation like MyManagerImpl implements MyManager
the pointcut is applied to the interface
method so MethodSignature
describes the method defined on MyManager
that doesn't have any annotation. the only way I've found to fix this is to inspect the class of the jp.getTarget()
object and retrieve the corresponding method.
Even after changing the retention policy like Bozho mentioned this call to get annotation returns null:
targetMethod.getAnnotation(Restricted.class);
What I found is you have to bind the annotation. Given the interface is declared like this:
@Retention(RetentionPolicy.RUNTIME)
public @interface Restricted {
String[] allowedRoles();
}
The advice would need to be declared like this:
@Before("@annotation( restrictedAnnotation )")
public Object processRequest(final ProceedingJoinPoint pjp, Restricted restrictedAnnotation) throws Throwable {
String[] roles = restrictedAnnotation.allowedRoles();
System.out.println("Allowed:" + roles);
}
What this does is bind the annotation to the parameter in the method signature, restrictedAnnotation. The part I am not sure about is how it gets the annotation type, it seems to be based on the parameter. And once you have the annotation you can get the values.
To whoever is still having problem after changing annotation retention to Runtime, you might be having the same problem I had: getMethod() returns interface method instead of the implementing class. So, if you have your annotations in the class then naturally getAnnotations() on the interface method returns null.
The following solution solved this problem:
final String methodName = pjp.getSignature().getName();
final MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
Method method = methodSignature.getMethod();
if (method.getDeclaringClass().isInterface()) {
method = pjp.getTarget().getClass().getDeclaredMethod(methodName, method.getParameterTypes());
}
and if you like, you have the option of handling interface annotations here too.
Some more comments available here: getting template method instance from ProceedingJoinPoint
Oleg
I assume @Restricted
is your annotation. If that is the case, make sure you have:
@Retention(RetentionPolicy.RUNTIME)
in your annotation definition. This means that the annotation is retained at runtime.