1. 程式人生 > >aop:config在shiro許可權註解中發揮的作用

aop:config在shiro許可權註解中發揮的作用

問題

spring-shiro.xml中通常會加aop配置,以使shiro認證註解(@RequiresPermissions、@RequiresRoles、@RequiresUser、@RequiresGuest)work。
通常配置如下

<aop:config />
    <!--許可權註解的advisor -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property
name="securityManager" ref="securityManager"/>
</bean>

但是我有一個問題!<aop:config/>沒有配置通知,也沒有配置切點,shiro的認證註解怎麼就work了呢?

我們注意到有個AuthorizationAttributeSourceAdvisor配置,它是一個通知器
類層次圖
這裡寫圖片描述

觀察類層次結構圖,可以看到它實現了pointcut,我們知道pointcut就是切點,它會判斷匹配哪些類,並返回方法匹配

public interface Pointcut {

    /**
     * Return the ClassFilter for this pointcut.
     * @return
the ClassFilter (never {@code null}) */
ClassFilter getClassFilter(); /** * Return the MethodMatcher for this pointcut. * @return the MethodMatcher (never {@code null}) */ MethodMatcher getMethodMatcher(); /** * Canonical Pointcut instance that always matches. */
Pointcut TRUE = TruePointcut.INSTANCE; }

pointcut中一共兩個介面方法,一個是getClassFilter,一個是getMethodMatcher

getClassFilter匹配所有類

AuthorizationAttributeSourceAdvisor的父類StaticMethodMatcherPointcut中,實現了getClassFiltergetMethodMatcher方法。

public abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut {

    private ClassFilter classFilter = ClassFilter.TRUE;


    /**
     * Set the {@link ClassFilter} to use for this pointcut.
     * Default is {@link ClassFilter#TRUE}.
     */
    public void setClassFilter(ClassFilter classFilter) {
        this.classFilter = classFilter;
    }

    @Override
    public ClassFilter getClassFilter() {
        return this.classFilter;
    }


    @Override
    public final MethodMatcher getMethodMatcher() {
        return this;
    }

}

繼續追蹤,類屬性classFilter是ClassFilter.TRUE,最終跟蹤到TrueClassFilter,matches方法始終返回true,所以AuthorizationAttributeSourceAdvisor匹配所有類

class TrueClassFilter implements ClassFilter, Serializable {

    public static final TrueClassFilter INSTANCE = new TrueClassFilter();

    /**
     * Enforce Singleton pattern.
     */
    private TrueClassFilter() {
    }

    @Override
    public boolean matches(Class<?> clazz) {
        return true;
    }
}

getMethodMatcher匹配所有加了認證註解的方法

再看方法匹配,注意StaticMethodMatcherPointcutgetMethodMatcher返回的是this,因為AuthorizationAttributeSourceAdvisor實現了MethodMatcher介面,所以返回的this就是AuthorizationAttributeSourceAdvisor本身。MethodMatchermatches方法用來判斷方法匹配。
可以看到它會匹配所有加了認證註解的方法。

 AuthorizationAttributeSourceAdvisor.java

 private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
            new Class[] {
                    RequiresPermissions.class, RequiresRoles.class,
                    RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class
            };
 public boolean matches(Method method, Class targetClass) {
        Method m = method;

        if ( isAuthzAnnotationPresent(m) ) {
            return true;
        }

        //The 'method' parameter could be from an interface that doesn't have the annotation.
        //Check to see if the implementation has it.
        if ( targetClass != null) {
            try {
                m = targetClass.getMethod(m.getName(), m.getParameterTypes());
                if ( isAuthzAnnotationPresent(m) ) {
                    return true;
                }
            } catch (NoSuchMethodException ignored) {
                //default return value is false.  If we can't find the method, then obviously
                //there is no annotation, so just use the default return value.
            }
        }

        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;
    }

aop:config

至今,我們有了一個完整的切面認識AuthorizationAttributeSourceAdvisor

  • 匹配所有類
  • 匹配所有加認證註解的方法

我們知道,<aop:config/>會掃描配置檔案中的所有advisor,併為其建立代理。正是有個<aop:config/>加上AuthorizationAttributeSourceAdvisor,所以認證註解才會work

總結

至此,我們就明白了,正是有了以下兩條的作用,才使得shiro認證註解可以正常work。

  • <aop:config/>會掃描配置檔案中的所有advisor,併為其建立代理
  • AuthorizationAttributeSourceAdvisor匹配所有類,匹配所有加了認證註解的方法