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源码分析