You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by "Nassos A. Michas" <na...@eurodyn.com> on 2010/11/09 14:49:35 UTC

Shiro + AspectJ - accessing variables in annotations

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-


Re: Shiro + AspectJ - accessing variables in annotations

Posted by "Nassos A. Michas" <na...@eurodyn.com>.
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: lhazlewood@apache.org
> To: user@shiro.apache.org
> 
> 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 <na...@eurodyn.com> 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-


RE: Shiro + AspectJ - accessing variables in annotations

Posted by Bryan Turner <in...@hotmail.com>.
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: lhazlewood@apache.org
To: user@shiro.apache.org

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 <na...@eurodyn.com> 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-
 		 	   		  

Re: Shiro + AspectJ - accessing variables in annotations

Posted by Les Hazlewood <lh...@apache.org>.
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
<na...@eurodyn.com>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-
>