Shiro注解认证授权实现原理

@Configuration
@Import(ShiroAnnotationProcessorConfiguration.class)
public class ShiroConfig {

}

// 注册注解的处理器,根据授权认证注解需要生成代理对象的后置处理器
public class ShiroAnnotationProcessorConfiguration {
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        // 创建代理对象的BeanPostProcessor
        return new DefaultAdvisorAutoProxyCreator();
    }

    @Bean
    protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        // 注解解析的切面
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

// 授权认证注解需要生成代理对象的切面,会根据是否存在注解来确定该切面是否可以应用上该切面
public class AuthorizationAttributeSourceAdvisor {
    // 当前切面需要运用的拦截器
    private Advice advice = EMPTY_ADVICE;

    // 支持的授权认证注解
    private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
            new Class[]{RequiresPermissions.class,
                    RequiresRoles.class,
                    RequiresUser.class,
                    RequiresGuest.class,
                    RequiresAuthentication.class};

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

    public void setAdvice(Advice advice) {
        this.advice = advice;
    }

    // 匹配当前切面是否可用,只要类,方法,父类,实现的接口,实现的接口方法中包含授权注解,都匹配成功
    public boolean matches(Method method, Class targetClass) {
        Method m = method;
        // 当前执行的方法中是否存在授权相关注解
        if (this.isAuthzAnnotationPresent(m)) {
            return true;
        }
        // 当前执行的方法中不存在授权注解,继续找接口或者
        if (targetClass != null) {
            // 获取父类方法(父类),接口方法(接口)是否存在授权注解
            m = targetClass.getMethod(m.getName(), m.getParameterTypes());
            return this.isAuthzAnnotationPresent(m) || this.isAuthzAnnotationPresent(targetClass);
        }

        return false;
    }

    // 判断方法中或者类中是否存在授权注解
    private boolean isAuthzAnnotationPresent(AnnotatedElement element) {
        for (Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES) {
            Annotation a = AnnotationUtils.findAnnotation(element, annClass);
            // 如果存在返回true
            if (a != null) {
                return true;
            }
        }
        return false;
    }

}

// 注解代理对象的统一拦截器入口,内部代理了具体的注解拦截器的处理逻辑
public class AopAllianceAnnotationsAuthorizingMethodInterceptor {
    // 当前拦截器代理的5个注解相关处理的拦截器
    protected Collection<AuthorizingAnnotationMethodInterceptor> methodInterceptors;

    public AopAllianceAnnotationsAuthorizingMethodInterceptor() {
        List<AuthorizingAnnotationMethodInterceptor> interceptors = new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);

        // 注解解析器
        AnnotationResolver resolver = new SpringAnnotationResolver();
        // 添加处理RequiresRoles的拦截器
        interceptors.add(new RoleAnnotationMethodInterceptor(resolver));
        // 添加处理RequiresPermissions的拦截器
        interceptors.add(new PermissionAnnotationMethodInterceptor(resolver));
        // 添加处理RequiresAuthentication的拦截器
        interceptors.add(new AuthenticatedAnnotationMethodInterceptor(resolver));
        // 添加处理RequiresUser的拦截器
        interceptors.add(new UserAnnotationMethodInterceptor(resolver));
        // 添加处理RequiresGuest的拦截器
        interceptors.add(new GuestAnnotationMethodInterceptor(resolver));

        this.methodInterceptors = interceptors;
    }

    // 代理的拦截方法
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        org.apache.shiro.aop.MethodInvocation mi = createMethodInvocation(methodInvocation);
        // 断言授权
        this.assertAuthorized(mi);
        // 继续执行下一个拦截器
        return mi.proceed();
    }

    protected void assertAuthorized(MethodInvocation methodInvocation) throws AuthorizationException {
        Collection<AuthorizingAnnotationMethodInterceptor> aamis = this.methodInterceptors;
        // 如果存在处理注解的拦截器
        if (aamis != null && !aamis.isEmpty()) {
            // 遍历所有支持的拦截器
            // AuthorizingAnnotationMethodInterceptor为具体拦截器的父类
            for (AuthorizingAnnotationMethodInterceptor aami : aamis) {
                // 只要支持处理该注解的拦截器都会执行
                if (aami.supports(methodInvocation)) {
                    // 执行授权认证的断言操作
                    aami.assertAuthorized(methodInvocation);
                }
            }
        }
    }

}

// 授权注解的通用方法拦截器
public class AuthorizingAnnotationMethodInterceptor {
    public void assertAuthorized(MethodInvocation mi) throws AuthorizationException {
        try {
            // 执行handler的处理逻辑,这个Handler在创建对应注解的拦截器就已经设置好固定处理注解的Handler
            AuthorizingAnnotationHandler handler = (AuthorizingAnnotationHandler) getHandler();
            // 使用具体的注解处理器进行断言
            handler.assertAuthorized(getAnnotation(mi);
        } catch (AuthorizationException ae) {
            if (ae.getCause() == null) {
                ae.initCause(new AuthorizationException("Not authorized to invoke method: " + mi.getMethod()));
            }
            throw ae;
        }
    }


}

// 解释两个,处理RequiresAuthentication注解,处理RequiresRoles注解
// 处理RequiresRoles注解
public class RoleAnnotationMethodInterceptor extends AuthorizingAnnotationMethodInterceptor {

    // RequiresRoles注解指定处理器
    public RoleAnnotationMethodInterceptor() {
        super(new RoleAnnotationHandler());
    }


}

// 授权注解的通用处理器
public class AuthorizingAnnotationHandler {
    // 授权注解的处理器,需要传递该Handler需要处理的注解
    public AuthorizingAnnotationHandler(Class<? extends Annotation> annotationClass) {
        super(annotationClass);
    }

    // 根据具体的注解进行断言的方法
    public abstract void assertAuthorized(Annotation a) throws AuthorizationException;

}

// 处理RequiresRoles注解的处理器
public class RoleAnnotationHandler extends AuthorizingAnnotationHandler {
    public RoleAnnotationHandler() {
        super(RequiresRoles.class);
    }

    // 断言
    public void assertAuthorized(Annotation a) throws AuthorizationException {
        // 如果不存在RequiresRoles注解,不处理
        if (!(a instanceof RequiresRoles)) {
            return;
        }
        // 获取注解中的角色信息
        RequiresRoles rrAnnotation = (RequiresRoles) a;
        String[] roles = rrAnnotation.value();
        // 如果只有一个,直接调用Suject的校验权限方法
        if (roles.length == 1) {
            /**
             * <pre>
             * 校验流程
             *    1. 先判断是否认证,如果没有认证,抛出认证异常
             *    2. 在调用securityManager(为AuthorizingSecurityManager的子类)的校验方法
             *    2.1 在该securityManager包含一个Authorizer授权器,该类型为ModularRealmAuthorizer
             *    2.2 最终是调用ModularRealmAuthorizer.hasRoles方法
             *    3. 断言ModularRealmAuthorizer设置的Realm是否为空(必须存在一个Realm才行)
             *    4. 遍历所有的授权Realm(实现了Authorizer的Realm,一般都是AuthorizingRealm),调用Realm的hasRole方法
             *    5. 获取该用户的授权信息,先根据用户查缓存,如果不存在,调用Realm的doGetAuthorizationInfo方法获取权限并缓存
             *    6. 最终从获取的权限信息中,判断是否存在指定的权限,如果不存在抛出UnauthorizedException异常
             * </pre>
             */
            getSubject().checkRole(roles[0]);
            return;
        }
        // 一些表达式的授权逻辑,和上面的逻辑一样
        // AND运算符,必须同时拥有多个权限
        if (Logical.AND.equals(rrAnnotation.logical())) {
            getSubject().checkRoles(Arrays.asList(roles));
            return;
        }
        // OR运算符,只需要拥有其中一个权限
        if (Logical.OR.equals(rrAnnotation.logical())) {
            boolean hasAtLeastOneRole = false;
            for (String role : roles) {
                if (getSubject().hasRole(role)) {
                    hasAtLeastOneRole = true;
                }
            }
            if (!hasAtLeastOneRole) {
                getSubject().checkRole(roles[0]);
            }
        }
    }
}

// 处理RequiresAuthentication注解的处理器
public class AuthenticatedAnnotationHandler extends AuthorizingAnnotationHandler {
    public AuthenticatedAnnotationHandler() {
        super(RequiresAuthentication.class);
    }

    // 断言
    public void assertAuthorized(Annotation a) throws UnauthenticatedException {
        // 如果Subject没有进行认证,抛出异常
        if (a instanceof RequiresAuthentication && !getSubject().isAuthenticated()) {
            throw new UnauthenticatedException("The current Subject is not authenticated.  Access denied.");
        }
    }
}

// 处理RequiresAuthentication注解
public class AuthenticatedAnnotationMethodInterceptor extends AuthorizingAnnotationMethodInterceptor {

    // RequiresAuthentication注解指定处理器
    public AuthenticatedAnnotationMethodInterceptor(AnnotationResolver resolver) {
        super(new AuthenticatedAnnotationHandler(), resolver);
    }


}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值