shiro学习15-访问权限控制-authorizingRealm,Authorizor

子云 2016-02-23

在经过前面的filterChainManager和FilterChainResolver,PatternMatcher之后就会找到访问某个路径的filter,然后filter中就检查当前的subejct是否具有需要的有某个角色或者是权限。这个时候就会调用subject.isPermitted或者是subject.hasRole方法。这个方法的调用类似于我们之前在登陆校验时的方法调用,会调用组成当前subejct的securityManager的这个方法:

publicboolean isPermitted(String permission) {

        return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);

}

·

我们继续查看securityManager的isPermitted方法,我们看一下这个方法是在AuthorizingSecurityManager这个类中。最终调用的是private Authorizer authorizer;这个属性的方法,我们现在就来看一下Authorizer。其实权限验证完全可以类比登录校验,登录校验的时候也有一个Authenticator,他是调用的reaml的信息,这个Authorizer也是调用的realm里面的信息。

在AuthorizingSecurityManager 的构造方法中就会构造一个authorizer实例,代码:

public AuthorizingSecurityManager() {

        super();

        this.authorizer = new ModularRealmAuthorizer();

}

看一下ModularRealmAuthorizer类中的属性:

Collection<Realm> realms,我们配置的realm。

PermissionResolver permissionResolver:用于将我们写的String类型的权限转化为Permission类型

RolePermissionResolver rolePermissionResolver  用于将我们写的String类型的角色转化为Role类型

通过这几个属性加上这个类的作用就能大致猜测一下他的调用过程,在校验某个subject能不能访问某个路径时根据配置的realm获得subject的权限或者角色,这个角色或者权限是String类型的,然后用两个resolver转化为Permission Role类型的,再根据filter中的操作进行判断能否访问。

所以最主要的是还是我们配置的realm,权限的判断最终的根据就是realm中的权限角色信息,其他的只是用来转化和进行验证操作的。

我们看一下这个类中的setRealms方法

publicvoid setRealms(Collection<Realm> realms) {

        this.realms = realms;

        applyPermissionResolverToRealms();

        applyRolePermissionResolverToRealms();

}

在配置了realm之后再将PermissionResolver和RolePermissionResolver传入到reaml中,这个不难解释,因为我们在realm中存的信息一定是String类型的,最终会String类型的换为Permission和Role两种类型,这个转换过程可以在Realm中进行也可以在Authorizer中进行,这里将两个resolver传入到reaml中可以发现是在realm中进行的转换。

下面查看它的realm属性是如何传进去的,我们在spring的xml中配置的realm是作为SecurityManager的属性传入的,所以我们看securityManager中的setReaml方法:

我是用的debug的方法慢慢看的,设置realm显示在RealmSecurityManager的setRealms方法中进行的,然后调用了afterRealmSet方法,然后调用的是AuthorizingSecurityManager类中的afterRealmsSet()这个方法,会将realm传入到ModularRealmAuthorizer属性中。到这里我们就弄清楚了访问控制的权限验证。

 

我们再看一下是如何将存储的字符串的权限和角色转化为Permission  Role类的:毫无疑问会用到前面说的xxxResolver类,前面说了两个resolver会传到Realm中,,我们使用的是realm是AuthorizingRealm的子类,在AuthorizingRealm中就有permissionResolver和permissionRoleResolver两个属性,用与将字符串转化为permission和Role。当调用subject.isPermitted(“xxx”)的时候会调用authorizingRealm的getAuthorizingInfo方法,获得用户的信息后调用isPermitted(Permission permission, AuthorizationInfo info),传入的就是info,这个方法里面的getPermission方法就会将info中的字符串的权限转化为permission

 

在这个AuthorizingRealm中还有一个属性:authorizationCache,这个就是用来缓存我们从realm中获得的用户的权限和角色的信息,但是默认情况下是不会启用的,并且将信息缓存在应用中是不太可取的,最好是将缓存放到redis中,因为将来我们很可能是tomcat集群,如果将缓存致多个tomcat中,在改变用户的权限和角色时会导致不同的tomcat中的信息的不一致,所以关于缓存最好放在一个单独的服务器中,比如用redis。

 

相关推荐

Mr丶Yang / 0评论 2016-11-04