开始正题前,先谈谈对继承与实现的一点点理解,敲了三年代码终于理解一点点继承与实现的妙用了,继承就是把大家公共的方法提做父类的方法,后面只要继承这个父类,就拥有了父类的所有方法,这样就减少了很多冗余代码; 实现就是接口先规范一些方法,我要调用接口里的方法帮我做一些事情,这时我并不知道这个方法具体是怎么实现的,后面我可以用各种不同的方式实现这个接口的方法,实现了哪个前面实际就调用哪个。 以下是实际举例: 1shiro的AuthorizingRealm类调用了接口PermissionResolver的resolvePermission方法把字符串转换成相应的Permission实例,这个时候它虽然调用了,但是它不知道具体是怎么转的。需要我们告诉它,于是,我们要实现接口PermissionResolver的resolvePermission方法,如下:
public class BitAndWildPermissionResolver implements PermissionResolver {
@Override
public Permission resolvePermission(String permissionString) {
if(permissionString.startsWith("+")) {
return new BitPermission(permissionString);
}
return new WildcardPermission(permissionString);
}
}
RolePermissionResolver 的方法resolvePermissionsInRole同理。
一、授权流程
1、验证主体是否拥有某些权限,无非是调用以下几个方法进行判断:
hasRole,hasAllRoles,hasRoles,checkRole,checkRoles isPermitted,isPermittedAll,checkPermission,checkPermissions
2、首先调用Subject.isPermitted*/hasRole接口,其会委托给SecurityManager,而SecurityManager接着会委托给Authorizer;即最后谁实现了Authorizer的isPermitted/hasRole,调用的就是谁。shiro中Authorizer具体实现类有如下:
3、Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过PermissionResolver把字符串转换成相应的Permission实例;如类AuthorizingRealm调用了resolvePermission方法把字符串转换成相应的Permission实例。
public boolean isPermitted(PrincipalCollection principals, String permission) {
Permission p = getPermissionResolver().resolvePermission(permission);
return isPermitted(principals, p);
}
resolvePermission方法要自己去实现,如:
public class BitAndWildPermissionResolver implements PermissionResolver {
@Override
public Permission resolvePermission(String permissionString) {
if(permissionString.startsWith("+")) {
return new BitPermission(permissionString);
}
return new WildcardPermission(permissionString);
}
}
4、在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;如AuthorizingRealm类做了的如下这些事情,这里它调用getAuthorizationInfo方法获取Subject相应的角色/权限。
public boolean isPermitted(PrincipalCollection principals, String permission) {
Permission p = getPermissionResolver().resolvePermission(permission);
return isPermitted(principals, p);
}
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
AuthorizationInfo info = getAuthorizationInfo(principals);
return isPermitted(permission, info);
}
private 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;
}
5、Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole*会返回true,否则返回false表示授权失败。
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;
}
ModularRealmAuthorizer进行多Realm匹配流程:
1、首先检查相应的Realm是否实现了实现了Authorizer;
2、如果实现了Authorizer,那么接着调用其相应的isPermitted*/hasRole*接口进行匹配;
3、如果有一个Realm匹配那么将返回true,否则返回false。
总结:Authorizer的职责是进行授权(访问控制),是Shiro API中授权核心的入口点,其提供了相应的角色/权限判断接口。SecurityManager继承了Authorizer接口,且提供了ModularRealmAuthorizer用于多Realm时的授权匹配。PermissionResolver用于解析权限字符串到Permission实例,而RolePermissionResolver用于根据角色解析相应的权限集合。