This is an automated email from the ASF dual-hosted git repository.

lprimak pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/shiro.git


The following commit(s) were added to refs/heads/main by this push:
     new 34baf83d4 bugfix(aop/guice): add support for retrieving annotations 
from superc… (#2860)
34baf83d4 is described below

commit 34baf83d4bece6d3607ca34109240276e923be70
Author: Lenny Primak <[email protected]>
AuthorDate: Sun Aug 16 12:44:24 2026 -0500

    bugfix(aop/guice): add support for retrieving annotations from superc… 
(#2860)
---
 .../apache/shiro/aop/DefaultAnnotationResolver.java | 14 +++++++++++++-
 .../apache/shiro/aop/AnnotationResolverTest.java    | 21 +++++++++++++++++++++
 .../aspectj/ShiroAnnotationAuthorizingAspect.java   | 17 +++++++++++------
 .../shiro/aspectj/RestrictedDummyService.java       |  4 ++--
 4 files changed, 47 insertions(+), 9 deletions(-)

diff --git 
a/core/src/main/java/org/apache/shiro/aop/DefaultAnnotationResolver.java 
b/core/src/main/java/org/apache/shiro/aop/DefaultAnnotationResolver.java
index c020588ce..3c76bacb6 100644
--- a/core/src/main/java/org/apache/shiro/aop/DefaultAnnotationResolver.java
+++ b/core/src/main/java/org/apache/shiro/aop/DefaultAnnotationResolver.java
@@ -63,8 +63,20 @@ public class DefaultAnnotationResolver implements 
AnnotationResolver {
         if (annotation == null) {
             Object miThis = mi.getThis();
             //SHIRO-473 - miThis could be null for static methods, just return 
null
-            annotation = miThis != null ? 
miThis.getClass().getAnnotation(clazz) : null;
+            annotation = miThis != null ? 
getAnnotationFromClassHierarchy(miThis.getClass(), clazz) : null;
         }
         return annotation;
     }
+
+    private Annotation getAnnotationFromClassHierarchy(Class<?> targetClass, 
Class<? extends Annotation> clazz) {
+        Class<?> current = targetClass;
+        while (current != null) {
+            Annotation annotation = current.getDeclaredAnnotation(clazz);
+            if (annotation != null) {
+                return annotation;
+            }
+            current = current.getSuperclass();
+        }
+        return null;
+    }
 }
diff --git 
a/core/src/test/java/org/apache/shiro/aop/AnnotationResolverTest.java 
b/core/src/test/java/org/apache/shiro/aop/AnnotationResolverTest.java
index c46b15f07..af4f09e24 100644
--- a/core/src/test/java/org/apache/shiro/aop/AnnotationResolverTest.java
+++ b/core/src/test/java/org/apache/shiro/aop/AnnotationResolverTest.java
@@ -42,6 +42,16 @@ public class AnnotationResolverTest {
         }
     }
 
+    @SuppressWarnings("unused")
+    @RequiresRoles("admin")
+    private static class ParentFixture {
+        public void operateParent() {
+        }
+    }
+
+    private static final class ChildFixture extends ParentFixture {
+    }
+
     DefaultAnnotationResolver annotationResolver = new 
DefaultAnnotationResolver();
 
     @Test
@@ -64,6 +74,17 @@ public class AnnotationResolverTest {
         assertThat(annotationResolver.getAnnotation(methodInvocation, 
RequiresUser.class)).isNotNull();
     }
 
+    @Test
+    void testAnnotationFoundFromSuperclass() throws SecurityException, 
NoSuchMethodException {
+        ChildFixture childFixture = new ChildFixture();
+        MethodInvocation methodInvocation = createMock(MethodInvocation.class);
+        Method method = ParentFixture.class.getDeclaredMethod("operateParent");
+        expect(methodInvocation.getMethod()).andReturn(method);
+        expect(methodInvocation.getThis()).andReturn(childFixture);
+        replay(methodInvocation);
+        assertThat(annotationResolver.getAnnotation(methodInvocation, 
RequiresRoles.class)).isNotNull();
+    }
+
     @Test
     void testNullMethodInvocation() throws SecurityException, 
NoSuchMethodException {
         MethodInvocation methodInvocation = createMock(MethodInvocation.class);
diff --git 
a/support/aspectj/src/main/aspect/org/apache/shiro/aspectj/ShiroAnnotationAuthorizingAspect.java
 
b/support/aspectj/src/main/aspect/org/apache/shiro/aspectj/ShiroAnnotationAuthorizingAspect.java
index 913cfae0a..b02488ce5 100644
--- 
a/support/aspectj/src/main/aspect/org/apache/shiro/aspectj/ShiroAnnotationAuthorizingAspect.java
+++ 
b/support/aspectj/src/main/aspect/org/apache/shiro/aspectj/ShiroAnnotationAuthorizingAspect.java
@@ -24,23 +24,28 @@ import org.aspectj.lang.annotation.Before;
 import org.aspectj.lang.annotation.Pointcut;
 
 /**
- * Aspect that adds a before advice for each invocation of an annotated method.
+ * Aspect that adds a before advice for each invocation of an annotated method 
or class.
  */
-@Aspect()
+@Aspect
 public class ShiroAnnotationAuthorizingAspect {
 
-    private static final String pointCupExpression =
+    private static final String pointCutExpression =
             
"execution(@org.apache.shiro.authz.annotation.RequiresAuthentication * *(..)) 
|| " +
+                    "execution(* 
(@org.apache.shiro.authz.annotation.RequiresAuthentication *).*(..)) || " +
                     
"execution(@org.apache.shiro.authz.annotation.RequiresGuest * *(..)) || " +
+                    "execution(* 
(@org.apache.shiro.authz.annotation.RequiresGuest *).*(..)) || " +
                     
"execution(@org.apache.shiro.authz.annotation.RequiresPermissions * *(..)) || " 
+
+                    "execution(* 
(@org.apache.shiro.authz.annotation.RequiresPermissions *).*(..)) || " +
                     
"execution(@org.apache.shiro.authz.annotation.RequiresRoles * *(..)) || " +
-                    "execution(@org.apache.shiro.authz.annotation.RequiresUser 
* *(..))";
+                    "execution(* 
(@org.apache.shiro.authz.annotation.RequiresRoles *).*(..)) || " +
+                    "execution(@org.apache.shiro.authz.annotation.RequiresUser 
* *(..)) || " +
+                    "execution(* 
(@org.apache.shiro.authz.annotation.RequiresUser *).*(..))";
 
-    @Pointcut(pointCupExpression)
+    @Pointcut(pointCutExpression)
     public void anyShiroAnnotatedMethod() {
     }
 
-    @Pointcut(pointCupExpression)
+    @Pointcut(pointCutExpression)
     void anyShiroAnnotatedMethodCall(JoinPoint thisJoinPoint) {
     }
 
diff --git 
a/support/aspectj/src/test/java/org/apache/shiro/aspectj/RestrictedDummyService.java
 
b/support/aspectj/src/test/java/org/apache/shiro/aspectj/RestrictedDummyService.java
index 6c101889c..e8314d032 100644
--- 
a/support/aspectj/src/test/java/org/apache/shiro/aspectj/RestrictedDummyService.java
+++ 
b/support/aspectj/src/test/java/org/apache/shiro/aspectj/RestrictedDummyService.java
@@ -21,11 +21,11 @@ package org.apache.shiro.aspectj;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 /**
- * Extends the secure dummy service and makes it some access more restrictive.
+ * Extends the secure dummy service and applies an additional class-level 
restriction.
  */
+@RequiresPermissions("dummy:admin")
 public class RestrictedDummyService extends SecuredDummyService {
 
-    @RequiresPermissions("dummy:admin")
     public void retrieve() {
         log("retrieve *RESTRICTED*");
         super.retrieve();

Reply via email to