Shiro权限注解原理

前不久刚学会使用权限注解(),开始思索了一番。最开始猜测实现方式是注解@Aspect,具体实现方式类似如下所示(切面记录审计日志)。后来发现并非如此,所以特地分析一下源码。
@Component
@Aspect
public class AuditLogAspectConfig {
    @Pointcut("@annotation(com.ygsoft.ecp.mapp.basic.audit.annotation.AuditLog) || @annotation(com.ygsoft.ecp.mapp.basic.audit.annotation.AuditLogs)")
    public void pointcut() {       
    }

@After(value="pointcut()")
    public void after(JoinPoint joinPoint) {
        //执行的逻辑
    }
    ...
}

2|0权限注解的源码分析

DefaultAdvisorAutoProxyCreator这个类实现了BeanProcessor接口,当ApplicationContext读取所有的Bean配置信息后,这个类将扫描上下文,寻找所有的Advistor(一个Advisor是一个切入点和一个通知的组成),将这些Advisor应用到所有符合切入点的Bean中。
@Configuration
public class ShiroAnnotationProcessorConfiguration extends AbstractShiroAnnotationProcessorConfiguration{
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        return super.defaultAdvisorAutoProxyCreator();
    }

@Bean
    protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        return super.authorizationAttributeSourceAdvisor(securityManager);
    }

}

AuthorizationAttributeSourceAdvisor继承了StaticMethodMatcherPointcutAdvisor,如下代码所示,只匹配五个注解,也就是说只对这五个注解标注的类或者方法增强。StaticMethodMatcherPointcutAdvisor是静态方法切点的抽象基类,默认情况下它匹配所有的类。StaticMethodMatcherPointcut包括两个主要的子类分别是NameMatchMethodPointcut和AbstractRegexpMethodPointcut,前者提供简单字符串匹配方法前面,而后者使用正则表达式匹配方法前面。动态方法切点:DynamicMethodMatcerPointcut是动态方法切点的抽象基类,默认情况下它匹配所有的类,而且也已经过时,建议使用DefaultPointcutAdvisor和DynamicMethodMatcherPointcut动态方法代替。另外还需关注构造器中的传入的AopAllianceAnnotationsAuthorizingMethodInterceptor。
public class AuthorizationAttributeSourceAdvisor extends StaticMethodMatcherPointcutAdvisor {

private static final Logger log = LoggerFactory.getLogger(AuthorizationAttributeSourceAdvisor.class);

private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
            new Class[] {
                    RequiresPermissions.class, RequiresRoles.class,
                    RequireSUSEr.class, RequiresGuest.class, RequiresAuthentication.class
            };

protected SecurityManager securityManager = null;

public AuthorizationAttributeSourceAdvisor() {
        setAdvice(new AopAllianceAnnotationsAuthorizingMethodInterceptor());
    }

public SecurityManager getSecurityManager() {
        return securityManager;
    }

public void setSecurityManager(org.apache.shiro.mgt.SecurityManager securityManager) {
        this.securityManager = securityManager;
    }

public boolean matches(Method method, Class targetClass) {
        Method m = method;

if ( isAuthzAnnotationPresent(m) ) {
            return true;
        }
       
        if ( targetClass != null) {
            try {
                m = targetClass.getMethod(m.getName(), m.getParameterTypes());
                if ( isAuthzAnnotationPresent(m) ) {
                    return true;
                }
            } catch (NoSuchMethodException ignored) {
               
            }
        }

return false;
    }

private boolean isAuthzAnnotationPresent(Method method) {
        for( Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES ) {
            Annotation a = AnnotationUtils.findAnnotation(method, annClass);
            if ( a != null ) {
                return true;
            }
        }
        return false;
    }

}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/ca6c012f65e13e14787202e4142b4069.html