shiro 验证角色,权限过程分析

首先说明,在shiro中,实际应用中在方法上添加 RequiresPermissions 或者 RequiresRoles 注解会触发aop执行验证当前Subject是否有相关权限或者角色的代码。

RequiresPermissions 的注解处理器中调用 getSubject().isPermitted(String permission) 验证。

RequiresRoles  的注解处理器中调用 getSubject().hasRole(String role) 验证。

下面从调用 getSubject().isPermitted(String permission) 开始分析整个调用过程

步骤1:默认执行DelegatingSubject中的方法:

public boolean isPermitted(String permission) {
        return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);
    }

首先验证实例字段  PrincipalCollection principals;长度不为0,然后调用securityManager验证是否有此权限

步骤2:securityManager使用内容实例变量 Authorizer authorizer来验证权限

public boolean isPermitted(PrincipalCollection principals, String permissionString) {
        return this.authorizer.isPermitted(principals, permissionString);
    }

步骤3:此时authorizer的默认实现类ModularRealmAuthorizer验证权限

 public boolean isPermitted(PrincipalCollection principals, String permission) {
        assertRealmsConfigured();
        for (Realm realm : getRealms()) {
            if (!(realm instanceof Authorizer)) continue;
            if (((Authorizer) realm).isPermitted(principals, permission)) {
                return true;
            }
        }
        return false;
    }

可以看出,最终和验证登录一样,登录的时候把realm转换为Realm接口调用身份认证接口,而现在是把realm转换为Authorizer,调用isPermitted验证权限。

步骤4:此时调用 抽象类 abstract class AuthorizingRealm中的方法,该类实现了接口Authorizer 的isPermitted方法

public boolean isPermitted(PrincipalCollection principals, String permission) {
        //把permission字符串转换为permission接口实现类的实例,例如String permission="aaa:bbb";
         //会转变成接口Permission实现类中的实例字段,分成aaa和bbb两个权限放在集合中存放
        Permission p = getPermissionResolver().resolvePermission(permission);
        return isPermitted(principals, p);
    }


public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        //getAuthorizationInfo(principals)调用的就是AuthorizingRealm实现的方法了
        AuthorizationInfo info = getAuthorizationInfo(principals);
        return isPermitted(permission, info);
    }

 

 

步骤5:AuthorizingRealm实现的getAuthorizationInfo(principals)

 protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {

        if (principals == null) {
            return null;
        }

        AuthorizationInfo info = null;

        Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
        if (cache != null) {
           
            //先到缓存中找
            Object key = getAuthorizationCacheKey(principals);
            info = cache.get(key);
          
        }


        if (info == null) {
            // 如果缓存中没有找到,则调用模板方法,就是我们继承此类实现的doGetAuthorizationInfo 
            //抽象方法
            info = doGetAuthorizationInfo(principals);
           
            if (info != null && cache != null) {
              
                Object key = getAuthorizationCacheKey(principals);
                cache.put(key, info);
            }
        }

        return info;
    }

步骤6:现在已经拿到AuthorizationInfo info,这个实例中包含着我们往里面放的权限集合,doGetAuthorizationInfo(principals):

Set<String> permsSet = new HashSet<String>();
permsSet.add("lightsaber");
permsSet.add("wield");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setStringPermissions(permsSet);
return info;

现在回到了步骤4里面的方法:

public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        //getAuthorizationInfo(principals)调用的就是AuthorizingRealm实现的方法了
        AuthorizationInfo info = getAuthorizationInfo(principals);
        return isPermitted(permission, info);
    }

继续这个类里面的方法,验证权限:

 protected boolean isPermitted(Permission permission, AuthorizationInfo info) {
        Collection<Permission> perms = getPermissions(info);
        if (perms != null && !perms.isEmpty()) {
            for (Permission perm : perms) {
                if (perm.implies(permission)) {
                    return true;
                }
            }
        }
        return false;
    }

获取true或false返回到最开始的getSubject().isPermitted(String permission) ,同理验证角色的过程比较相似,只要在doGetAuthorizationInfo(principals)方法中设置 info.setRoles();

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值