1.自定义注解 @SalmonRequiresPermission

 1 import java.lang.annotation.ElementType;
 2 import java.lang.annotation.Retention;
 3 import java.lang.annotation.RetentionPolicy;
 4 import java.lang.annotation.Target;
 5 
 6 import org.apache.shiro.authz.annotation.Logical;
 7 
 8 /**
 9  * SalmonRequiresPermissions is
10  *
11  * @author zzt
12  * @date 2020/2/22 16:25:00
13  */
14 @Target({ElementType.TYPE, ElementType.METHOD})
15 @Retention(RetentionPolicy.RUNTIME)
16 public @interface SalmonRequiresPermissions {
17     String[] value();
18 
19     Logical logical() default Logical.AND;
20 
21     // 描述
22     String[] description();
23 }

  这里只是简单的增加了一个描述,可根据需求自行扩展。

 

2.自定义注解处理器,继承 AuthorizingAnnotationHandler

 1 import java.lang.annotation.Annotation;
 2 
 3 import org.apache.shiro.authz.AuthorizationException;
 4 import org.apache.shiro.authz.annotation.Logical;
 5 import org.apache.shiro.authz.annotation.RequiresPermissions;
 6 import org.apache.shiro.authz.aop.AuthorizingAnnotationHandler;
 7 import org.apache.shiro.subject.Subject;
 8 
 9 /**
10  * SalmonPermissionAuthorizingAnnotationHandler is
11  *
12  * @author zzt
13  * @date 2020/2/25 11:43:00
14  */
15 public class SalmonPermissionAuthorizingAnnotationHandler extends AuthorizingAnnotationHandler {
16 
17     // 继承父类构造器,注入SalmonRequiresPermissions注解
18     public SalmonPermissionAuthorizingAnnotationHandler() {
19         super(SalmonRequiresPermissions.class);
20     }
21 
22     protected String[] getAnnotationValue(Annotation annotation) {
23         SalmonRequiresPermissions srpAnnotation = (SalmonRequiresPermissions)annotation;
24         return srpAnnotation.value();
25     }
26 
27     @Override
28     public void assertAuthorized(Annotation annotation) throws AuthorizationException {
29         if (annotation instanceof SalmonRequiresPermissions) {
30             SalmonRequiresPermissions srpAnnotation = (SalmonRequiresPermissions)annotation;
31             String[] perms = this.getAnnotationValue(annotation);
32             Subject subject = this.getSubject();
33             if (perms.length == 1) {
34                 subject.checkPermission(perms[0]);
35             } else if (Logical.AND.equals(srpAnnotation.logical())) {
36                 this.getSubject().checkPermissions(perms);
37             } else {
38                 if (Logical.OR.equals(srpAnnotation.logical())) {
39                     boolean hasAtLeastOnePermission = false;
40 
41                     for (int i = 0; i < perms.length; ++i) {
42                         String permission = perms[i];
43                         if (this.getSubject().isPermitted(permission)) {
44                             hasAtLeastOnePermission = true;
45                         }
46                     }
47                     if (!hasAtLeastOnePermission) {
48                         this.getSubject().checkPermission(perms[0]);
49                     }
50                 }
51             }
52         }
53     }
54 }

 

3.自定义Shiro拦截处理类,继承 AuthorizingAnnotationMethodInterceptor

 1 import org.apache.shiro.aop.AnnotationResolver;
 2 import org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor;
 3 
 4 /**
 5  * SalmonPermissionAuthorizingAnnotationMethodInterceptor is
 6  *
 7  * @author zzt
 8  * @date 2020/2/25 11:44:00
 9  */
10 public class SalmonPermissionAuthorizingAnnotationMethodInterceptor extends AuthorizingAnnotationMethodInterceptor {
11 
12     public SalmonPermissionAuthorizingAnnotationMethodInterceptor() {
13         super(new SalmonPermissionAuthorizingAnnotationHandler());
14     }
15 
16     public SalmonPermissionAuthorizingAnnotationMethodInterceptor(AnnotationResolver annotationResolver) {
17         super(new SalmonPermissionAuthorizingAnnotationHandler(), annotationResolver);
18     }
19 }

 

4.自定义AOP拦截,继承 AopAllianceAnnotationsAuthorizingMethodInterceptor

 1 import org.apache.shiro.spring.aop.SpringAnnotationResolver;
 2 import org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor;
 3 
 4 /**
 5  * SalmonPermissionAopAllianceAnnotationsAuthorizingMethodInterceptor is
 6  *
 7  * @author zzt
 8  * @date 2020/2/25 11:45:00
 9  */
10 public class SalmonAopAllianceAnnotationsAuthorizingMethodInterceptor extends AopAllianceAnnotationsAuthorizingMethodInterceptor {
11 
12     public SalmonAopAllianceAnnotationsAuthorizingMethodInterceptor() {
13         super();
14         this.methodInterceptors.add(
15                 new SalmonPermissionAuthorizingAnnotationMethodInterceptor(new SpringAnnotationResolver()));
16     }
17 }

 

5.添加新注解支持,继承 AuthorizationAttributeSourceAdvisor

 1 import java.lang.annotation.Annotation;
 2 import java.lang.reflect.Method;
 3 
 4 import org.apache.shiro.authz.annotation.RequiresAuthentication;
 5 import org.apache.shiro.authz.annotation.RequiresGuest;
 6 import org.apache.shiro.authz.annotation.RequiresPermissions;
 7 import org.apache.shiro.authz.annotation.RequiresRoles;
 8 import org.apache.shiro.authz.annotation.RequiresUser;
 9 import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
10 import org.springframework.core.annotation.AnnotationUtils;
11 
12 /**
13  * SalmonPermissionAuthorizationAttributeSourceAdvisor is
14  *
15  * @author zzt
16  * @date 2020/2/25 10:49:00
17  */
18 public class SalmonAuthorizationAttributeSourceAdvisor extends AuthorizationAttributeSourceAdvisor {
19 
20     private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
21             new Class[]{SalmonRequiresPermissions.class, RequiresPermissions.class, RequiresRoles.class,
22                     RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class};
23 
24     public SalmonAuthorizationAttributeSourceAdvisor() {
25         setAdvice(new SalmonAopAllianceAnnotationsAuthorizingMethodInterceptor());
26     }
27 
28     @Override
29     public boolean matches(Method method, Class targetClass) {
30         Method m = method;
31         if (this.isAuthzAnnotationPresent(method)) {
32             return true;
33         } else {
34             if (targetClass != null) {
35                 try {
36                     m = targetClass.getMethod(m.getName(), m.getParameterTypes());
37                     return this.isAuthzAnnotationPresent(m) || this.isAuthzAnnotationPresent(targetClass);
38                 } catch (NoSuchMethodException var5) {
39                 }
40             }
41 
42             return false;
43         }
44     }
45 
46     @SuppressWarnings("Duplicates")
47     private boolean isAuthzAnnotationPresent(Class<?> targetClazz) {
48         Class[] authzAnnotationClasses = AUTHZ_ANNOTATION_CLASSES;
49 
50         for (int i = 0; i < authzAnnotationClasses.length; ++i) {
51             Class<? extends Annotation> annClass = authzAnnotationClasses[i];
52             Annotation a = AnnotationUtils.findAnnotation(targetClazz, annClass);
53             if (a != null) {
54                 return true;
55             }
56         }
57 
58         return false;
59     }
60 
61     @SuppressWarnings("Duplicates")
62     private boolean isAuthzAnnotationPresent(Method method) {
63         Class[] authzAnnotationClasses = AUTHZ_ANNOTATION_CLASSES;
64 
65         for (int i = 0; i < authzAnnotationClasses.length; ++i) {
66             Class<? extends Annotation> annClass = authzAnnotationClasses[i];
67             Annotation a = AnnotationUtils.findAnnotation(method, annClass);
68             if (a != null) {
69                 return true;
70             }
71         }
72 
73         return false;
74     }
75 }

 

6.ShiroConfig添加配置,使用自定义 AuthorizationAttributeSourceAdvisor

1   // 添加自定义注解支持
2     @Bean
3     public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
4             DefaultWebSecurityManager securityManager) {
5         AuthorizationAttributeSourceAdvisor advisor = new SalmonAuthorizationAttributeSourceAdvisor();
6         advisor.setSecurityManager(securityManager);
7         return advisor;
8     }

 

 

 

参考文章:

https://my.oschina.net/cloudcross/blog/1924116 基于shiro的自定义注解扩展

https://blog.csdn.net/weixin_33909059/article/details/88856993 自定义Shiro注解

https://blog.csdn.net/u013219624/article/details/83589863 shiro源码分析之自定义注解RequiredPermission(可代替RequiresPermissions)

https://blog.csdn.net/xiewenfeng520/article/details/89447749 apache shiro框架@RequiresPermissions源码分析