Hello Bryan, Les, list,

I was trying today a little proof of concept, basically trying to access member 
vars which is what my team is firstly interested for. Scanning for the 
annotations and using a special instance declaration prefix (I used "#") I 
could annotate my methods as:

@RequiresPermissions({"forum:readTopic:#topicID"}) 

and by modifying BeforeAdviceMethodInvocationAdapter as:

Map<String, String> annotationSub = new HashMap<String, String>();
RequiresPermissions annotation =
     
((MethodSignature)aJoinPoint.getSignature()).getMethod().getAnnotation(RequiresPermissions.class);
for (String annotationVal : annotation.value()) {
     if (annotationVal.matches(".*:.*:#.*")) {
          String toSub = annotationVal.substring(annotationVal.lastIndexOf(":") 
+ 2);
          if (!annotationSub.containsKey(toSub)) {
               annotationSub.put(toSub, 
(String)PropertyUtils.getProperty(aJoinPoint.getThis(), toSub));
          }
     }
}

I could therefore end up with a map with key=the original annotation instance 
name (i.e. "topicID") and a value=the result from getTopicID() method of the 
annotated class. Note: The map may need to be enhanced with extra info or 
according to the possible answer below be replaced altogether; for now it just 
provides a place to hold the data acquired in runtime.

The question now is how to replace the original annotation with the updated one 
(that can be re-constructed using the above Map). At a glance, I see the 
following options:
1/ Dynamically update the original class annotation. As far as I know, it is 
not possible to change an annotation's value at runtime unless you use 
something like Javassist. Wouldn't that be of an overkill, especially 
considering that such security checks take place for every single user action?
2/ Find a way to construct a new method signature (updated using the Map above) 
to pass it to BeforeAdviceMethodInvocationAdapter's constructor. As far as I 
know this is not really an option considering that (the original) annotations 
end up in the bytecode.
3/ Modify Shiro's AuthorizingMethodInterceptor with an overloaded invoke() that 
takes into account the above Map (yikes!).
4/ Some AspectJ-magic? :)
5/ ???

This is just some food for thought. If you have any ideas/suggestions I would 
gladly experiment some more.


-n-

p.s. In a similar fashion, annotated method's args can also be supported using 
aJoinPoint.getArgs() in BeforeAdviceMethodInvocationAdapter. Of course, as 
Bryan correctly mentioned, you need debug info in your bytecode to access the 
actual names of the args but I guess BeforeAdviceMethodInvocationAdapter could 
be modified accordingly to support both approaches, e.g. "@topicID" when debug 
info is available and something like "@@arg0" when it's not or even something 
more crazy :) like "@topicID/0" to allow one set of annotations to work in all 
situations regardless of how the code was built.


On 10 Νοε 2010, at 12:50 π.μ., Bryan Turner wrote:

> Parameter names are available at runtime if the code is compiled with debug 
> information (even in production environments, it is not uncommon for the 
> release build to include this). Spring uses ASM internally to parse the names 
> out of the bytecode, using its LocalVariableTableParameterNameDiscoverer. For 
> Spring-based systems that always compile with debugging information, this 
> might be a solid approach.
> 
> Otherwise, a fallback approach that allows referring to parameters by number 
> (1-based) or index (0-based) might be a good catch-all solution that would 
> work in any AOP environment.
> 
> I'd be happy to help contribute an implementation of this feature.
> 
> Bryan
> 
> Date: Tue, 9 Nov 2010 14:30:10 -0800
> Subject: Re: Shiro + AspectJ - accessing variables in annotations
> From: [email protected]
> To: [email protected]
> 
> Hi Nassos,
> 
> This is something that we've wanted for Shiro annotations for a long time, 
> but no one has built it yet.  I'm not sure off the top of my head how to go 
> about doing this, but I remember seeing Spring AOP have the ability to 
> reference method arguments by parameter name (this was a while ago, but I 
> know it is possible).  Since that information is lost at runtime, I think is 
> a compile time feature.  That, or you annotate method parameters that could 
> be accessed at runtime.
> 
> I think it would be great if someone wanted to help with this!
> 
> Cheers,
> 
> Les
> 
> On Tue, Nov 9, 2010 at 5:49 AM, Nassos A. Michas <[email protected]> 
> wrote:
> Hello,
> 
> when using Shiro in a non-Spring webapp using the Shiro annotations and 
> AspectJ (as per the Shiro sample application) is it possible to somehow have 
> access to the member (or even the annotated method's) variables? For example, 
> am I somehow able to write something like:
> @RequiresPermission("forum:readTopic:#forumID")
> void readTopic(String forumID) {
> ...
> }
> or even,
> @RequiresPermission("forum:readTopic:#forum.forumID")
> void readTopic(MyBean forum) {
> ...
> }
> 
> If this is more of an AspectJ-related question please accept my apologies as 
> I'm not a big AspectJ user.
> 
> 
> Thanks!
> 
> -n-

Reply via email to