大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節(jié)點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 Shiro注解權(quán)限原理

Shiro注解權(quán)限原理

更新時間:2022-02-08 10:43:12 來源:動力節(jié)點 瀏覽845次

概述

分析一下源碼。

@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) {
        //執(zhí)行的邏輯
    }
    ...
}

權(quán)限注解的源碼分析

DefaultAdvisorAutoProxyCreator這個類實現(xiàn)了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是靜態(tài)方法切點的抽象基類,默認情況下它匹配所有的類。StaticMethodMatcherPointcut包括兩個主要的子類分別是NameMatchMethodPointcut和AbstractRegexpMethodPointcut,前者提供簡單字符串匹配方法前面,而后者使用正則表達式匹配方法前面。動態(tài)方法切點:DynamicMethodMatcerPointcut是動態(tài)方法切點的抽象基類,默認情況下它匹配所有的類,而且也已經(jīng)過時,建議使用DefaultPointcutAdvisor和DynamicMethodMatcherPointcut動態(tài)方法代替。另外還需關(guān)注構(gòu)造器中的傳入的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;
    }
}

AopAllianceAnnotationsAuthorizingMethodInterceptor在初始化時,interceptors添加了5個方法攔截器(都繼承自AuthorizingAnnotationMethodInterceptor),這5個攔截器分別對5種權(quán)限驗證的方法進行攔截,執(zhí)行invoke方法。

public class AopAllianceAnnotationsAuthorizingMethodInterceptor
        extends AnnotationsAuthorizingMethodInterceptor implements MethodInterceptor {
    public AopAllianceAnnotationsAuthorizingMethodInterceptor() {
        List<AuthorizingAnnotationMethodInterceptor> interceptors =
                new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);
        AnnotationResolver resolver = new SpringAnnotationResolver();        
        interceptors.add(new RoleAnnotationMethodInterceptor(resolver));
        interceptors.add(new PermissionAnnotationMethodInterceptor(resolver));
        interceptors.add(new AuthenticatedAnnotationMethodInterceptor(resolver));
        interceptors.add(new UserAnnotationMethodInterceptor(resolver));
        interceptors.add(new GuestAnnotationMethodInterceptor(resolver));
        setMethodInterceptors(interceptors);
    }    
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        org.apache.shiro.aop.MethodInvocation mi = createMethodInvocation(methodInvocation);
        return super.invoke(mi);
    }
    ...
}

AopAllianceAnnotationsAuthorizingMethodInterceptor的invoke方法,又會調(diào)用超類AuthorizingMethodInterceptor的invoke方法,在該方法中先執(zhí)行assertAuthorized方法,進行權(quán)限校驗,校驗不通過,拋出AuthorizationException異常,中斷方法;校驗通過,則執(zhí)行methodInvocation.proceed(),該方法也就是被攔截并且需要權(quán)限校驗的方法。

public abstract class AuthorizingMethodInterceptor extends MethodInterceptorSupport {
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        assertAuthorized(methodInvocation);
        return methodInvocation.proceed();
    }
    protected abstract void assertAuthorized(MethodInvocation methodInvocation) throws AuthorizationException;
}

assertAuthorized方法最終執(zhí)行的還是AuthorizingAnnotationMethodInterceptor.assertAuthorized,而AuthorizingAnnotationMethodInterceptor有5中的具體的實現(xiàn)類(RoleAnnotationMethodInterceptor, PermissionAnnotationMethodInterceptor, AuthenticatedAnnotationMethodInterceptor, UserAnnotationMethodInterceptor, GuestAnnotationMethodInterceptor)。

public abstract class AnnotationsAuthorizingMethodInterceptor extends   AuthorizingMethodInterceptor {  
    protected void assertAuthorized(MethodInvocation methodInvocation) throws AuthorizationException {
        //default implementation just ensures no deny votes are cast:
        Collection<AuthorizingAnnotationMethodInterceptor> aamis = getMethodInterceptors();
        if (aamis != null && !aamis.isEmpty()) {
            for (AuthorizingAnnotationMethodInterceptor aami : aamis) {
                if (aami.supports(methodInvocation)) {
                    aami.assertAuthorized(methodInvocation);
                }
            }
        }
    }
    ...
}

AuthorizingAnnotationMethodInterceptor的assertAuthorized,首先從子類獲取AuthorizingAnnotationHandler,再調(diào)用該實現(xiàn)類的assertAuthorized方法。

public abstract class AuthorizingAnnotationMethodInterceptor extends AnnotationMethodInterceptor
{
    public AuthorizingAnnotationMethodInterceptor( AuthorizingAnnotationHandler handler ) {
        super(handler);
    }
    public AuthorizingAnnotationMethodInterceptor( AuthorizingAnnotationHandler handler,
                                                   AnnotationResolver resolver) {
        super(handler, resolver);
    }
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        assertAuthorized(methodInvocation);
        return methodInvocation.proceed();
    }
    public void assertAuthorized(MethodInvocation mi) throws AuthorizationException {
        try {
            ((AuthorizingAnnotationHandler)getHandler()).assertAuthorized(getAnnotation(mi));
        }
        catch(AuthorizationException ae) {
            if (ae.getCause() == null) ae.initCause(new AuthorizationException("Not authorized to invoke method: " + mi.getMethod()));
            throw ae;
        }         
    }
}

現(xiàn)在分析其中一種實現(xiàn)類PermissionAnnotationMethodInterceptor,也是用的最多的,但是這個類的實際代碼很少,很明顯上述分析的getHandler在PermissionAnnotationMethodInterceptor中返回值為PermissionAnnotationHandler。

public class PermissionAnnotationMethodInterceptor extends AuthorizingAnnotationMethodInterceptor {
    public PermissionAnnotationMethodInterceptor() {
        super( new PermissionAnnotationHandler() );
    } 
    public PermissionAnnotationMethodInterceptor(AnnotationResolver resolver) {
        super( new PermissionAnnotationHandler(), resolver);
    }
}

在PermissionAnnotationHandler類中,終于發(fā)現(xiàn)實際的檢驗邏輯,還是調(diào)用的Subject.checkPermission()進行校驗。

public class PermissionAnnotationHandler extends AuthorizingAnnotationHandler {
    public PermissionAnnotationHandler() {
        super(RequiresPermissions.class);
    }
    protected String[] getAnnotationValue(Annotation a) {
        RequiresPermissions rpAnnotation = (RequiresPermissions) a;
        return rpAnnotation.value();
    }
    public void assertAuthorized(Annotation a) throws AuthorizationException {
        if (!(a instanceof RequiresPermissions)) return;
        RequiresPermissions rpAnnotation = (RequiresPermissions) a;
        String[] perms = getAnnotationValue(a);
        Subject subject = getSubject();
        if (perms.length == 1) {
            subject.checkPermission(perms[0]);
            return;
        }
        if (Logical.AND.equals(rpAnnotation.logical())) {
            getSubject().checkPermissions(perms);
            return;
        }
        if (Logical.OR.equals(rpAnnotation.logical())) {
            boolean hasAtLeastOnePermission = false;
            for (String permission : perms) if (getSubject().isPermitted(permission)) hasAtLeastOnePermission = true;
            if (!hasAtLeastOnePermission) getSubject().checkPermission(perms[0]);            
        }
    }
}

實現(xiàn)類似編程式AOP

定義一個注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String value() default "";
}

繼承StaticMethodMatcherPointcutAdvisor類,并實現(xiàn)相關(guān)的方法。

@SuppressWarnings("serial")
@Component
public class HelloAdvisor extends StaticMethodMatcherPointcutAdvisor{    
    public HelloAdvisor() {
        setAdvice(new LogMethodInterceptor());
    }
    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());
                return isAuthzAnnotationPresent(m);
            } catch (NoSuchMethodException ignored) {               
            }
        }
        return false;
    }
    private boolean isAuthzAnnotationPresent(Method method) {
        Annotation a = AnnotationUtils.findAnnotation(method, Log.class);
        return a!= null;
    }
}

實現(xiàn)MethodInterceptor接口,定義切面處理的邏輯

public class LogMethodInterceptor implements MethodInterceptor{
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Log log = invocation.getMethod().getAnnotation(Log.class);
        System.out.println("log: "+log.value());
        return invocation.proceed();    
    }
}

定義一個測試類,并添加Log注解

@Component
public class TestHello {
    @Log("test log")
    public String say() {
        return "ss";
    }
}

編寫啟動類,并且配置DefaultAdvisorAutoProxyCreator

@Configuration
public class TestBoot {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext("com.fzsyw.test");  
        TestHello th = ctx.getBean(TestHello.class);
        System.out.println(th.say());
    }    
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator da = new DefaultAdvisorAutoProxyCreator();
        da.setProxyTargetClass(true);
        return da;
    }
}

最終打印的結(jié)果如下,證明編程式的AOP生效。

log: test log
ss

總結(jié)

Shiro的注解式權(quán)限,使用確實方便,通過源碼也分析了它的實現(xiàn)原理,比較核心的是配置DefaultAdvisorAutoProxyCreator和繼承StaticMethodMatcherPointcutAdvisor。其中的5中權(quán)限注解,使用了統(tǒng)一一套代碼架構(gòu),用到了的模板模式,方便擴展。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 毛片免费在线视频 | 五月综合激情久久婷婷 | 成人淫片免费视频95视频 | 亚洲国产综合在线 | 久久国产影视免费精品 | 欧美天天性影院 | 毛片激情永久免费 | 成年女人视频播放免费观看 | 四虎影视在线永久免费看黄 | 欧美最猛性xxxx69交 | 波多野结衣一区二区三区高清在线 | 日本大蕉香蕉大视频在线观看 | 久久国产精品女 | 97在线免费视频 | 免费四影虎ww4hu10 | 国产欧美一区二区三区精品 | 日本大片免费一级 | 中文字幕专区 | 国产69精品久久久久999小说 | 久久久久久久久久免观看 | 亚洲天天更新 | 99影视| 老子影院无码午夜伦不卡 | 伊人成人在线视频 | 色午夜在线 | 狠狠激情五月综合婷婷俺 | 欧美精品久久久久久久小说 | 最刺激黄a大片免费观看下截 | 久久精品视频热 | aaaa级片 | 激情都市久久爱 | 亚洲高清中文字幕一区二区三区 | 日韩欧美亚洲国产一区二区三区 | 精品久久久久久久久久 | 欧美jlzz18性欧美 | 美国成人a免费毛片 | 久久穴 | 97视屏| 久久久精品视频在线观看 | 亚洲国产成人久久综合碰 | 国产精品亚洲一区二区三区久久 |