開始正題前,先談談對繼承與實現的一點點理解,敲了三年代碼終於理解一點點繼承與實現的妙用了,繼承就是把你們公共的方法提作父類的方法,後面只要繼承這個父類,就擁有了父類的全部方法,這樣就減小了不少冗餘代碼; 實現就是接口先規範一些方法,我要調用接口裏的方法幫我作一些事情,這時我並不知道這個方法具體是怎麼實現的,後面我能夠用各類不一樣的方式實現這個接口的方法,實現了哪一個前面實際就調用哪一個。 如下是實際舉例: 1shiro的AuthorizingRealm類調用了接口PermissionResolver的resolvePermission方法把字符串轉換成相應的Permission實例,這個時候它雖然調用了,可是它不知道具體是怎麼轉的。須要咱們告訴它,因而,咱們要實現接口PermissionResolver的resolvePermission方法,以下:java
public class BitAndWildPermissionResolver implements PermissionResolver { @Override public Permission resolvePermission(String permissionString) { if(permissionString.startsWith("+")) { return new BitPermission(permissionString); } return new WildcardPermission(permissionString); } }
RolePermissionResolver 的方法resolvePermissionsInRole同理。ide
1、受權流程code
一、驗證主體是否擁有某些權限,無非是調用如下幾個方法進行判斷:繼承
hasRole,hasAllRoles,hasRoles,checkRole,checkRoles isPermitted,isPermittedAll,checkPermission,checkPermissions接口
二、首先調用Subject.isPermitted*/hasRole接口,其會委託給SecurityManager,而SecurityManager接着會委託給Authorizer;即最後誰實現了Authorizer的isPermitted/hasRole,調用的就是誰。shiro中Authorizer具體實現類有以下:圖片
三、Authorizer是真正的受權者,若是咱們調用如isPermitted(「user:view」),其首先會經過PermissionResolver把字符串轉換成相應的Permission實例;如類AuthorizingRealm調用了resolvePermission方法把字符串轉換成相應的Permission實例。ip
public boolean isPermitted(PrincipalCollection principals, String permission) { Permission p = getPermissionResolver().resolvePermission(permission); return isPermitted(principals, p); }
resolvePermission方法要本身去實現,如:ci
public class BitAndWildPermissionResolver implements PermissionResolver { @Override public Permission resolvePermission(String permissionString) { if(permissionString.startsWith("+")) { return new BitPermission(permissionString); } return new WildcardPermission(permissionString); } }
四、在進行受權以前,其會調用相應的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; }
五、Authorizer會判斷Realm的角色/權限是否和傳入的匹配,若是有多個Realm,會委託給ModularRealmAuthorizer進行循環判斷,若是匹配如isPermitted*/hasRole*會返回true,不然返回false表示受權失敗。get
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匹配流程:
一、首先檢查相應的Realm是否實現了實現了Authorizer;
二、若是實現了Authorizer,那麼接着調用其相應的isPermitted*/hasRole*接口進行匹配;
三、若是有一個Realm匹配那麼將返回true,不然返回false。
總結:Authorizer的職責是進行受權(訪問控制),是Shiro API中受權核心的入口點,其提供了相應的角色/權限判斷接口。SecurityManager繼承了Authorizer接口,且提供了ModularRealmAuthorizer用於多Realm時的受權匹配。PermissionResolver用於解析權限字符串到Permission實例,而RolePermissionResolver用於根據角色解析相應的權限集合。