shiro——授權原理(源碼流程)

目錄

 

1. 授權入口

2. 源碼追蹤


1. 授權入口

subject.isPermitted(url); 這就是入口,如果用戶有這個url權限,那麼就返回true,如果沒有,則返回false。

2. 源碼追蹤

由於我們的Subject默認是由DelegatingSubject 類實現的,所以調用的是DelegatingSubject類的isPermitted(String url) 方法。

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

判斷該用戶是否有身份標識信息(多半是用戶名、電話等等,能夠唯一標識用戶),如果沒有,那肯定授權失敗,用戶無法訪問url。如果有,就繼續判斷,this.securityManager.isPermitted(this.getPrincipals(), permission);

這裏的securityManager 是我們的shiro配置文件中配置了的,本文是配置的DefaultSecurityManager類來實現的, 查看了DefaultSecurityManager類裏面,並沒有isPermitted方法,原來DefaultSecurityManager類繼承了AuthorizingSecurityManager類,而isPermitted方法是在AuthorizingSecurityManager類中,AuthorizingSecurityManager中的部分源碼:

private Authorizer authorizer = new ModularRealmAuthorizer();
public boolean isPermitted(PrincipalCollection principals, String permissionString) {
        return this.authorizer.isPermitted(principals, permissionString);
}

可以看到調用的是ModularRealmAuthorizer 類中的isPermitted方法,說明Authorizer 接口默認是由ModularRealmAuthorizer類實現的。

再看ModularRealmAuthorizer類中的isPermitted方法:

public boolean isPermitted(PrincipalCollection principals, String permission) {
        this.assertRealmsConfigured();
        Iterator var3 = this.getRealms().iterator();

        Realm realm;
        do {
            if (!var3.hasNext()) {
                return false;
            }

            realm = (Realm)var3.next();
        } while(!(realm instanceof Authorizer) || !((Authorizer)realm).isPermitted(principals, permission));

        return true;
}

可以看到,是調用的Realm中的isPermitted方法去授權驗證,那麼此時就要看我們自定義的Realm了。一般自定義的Realm都是繼承AuthorizingRealm類,而自定義Realm中就重寫了兩個方法:doGetAuthorizationInfo( ) 和 doGetAuthenticationInfo ( ) 方法。至於isPermitted方法,還是在AuthorizingRealm 類中,查看一下:

public boolean isPermitted(PrincipalCollection principals, String permission) {
        Permission p = this.getPermissionResolver().resolvePermission(permission);
        return this.isPermitted(principals, p);
}

public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        AuthorizationInfo info = this.getAuthorizationInfo(principals);
        return this.isPermitted(permission, info);
}

protected boolean isPermitted(Permission permission, AuthorizationInfo info) {
        Collection<Permission> perms = this.getPermissions(info);
        if (perms != null && !perms.isEmpty()) {
            Iterator var4 = perms.iterator();

            while(var4.hasNext()) {
                Permission perm = (Permission)var4.next();
                if (perm.implies(permission)) {
                    return true;
                }
            }
        }

        return false;
    }

protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            return null;
        } else {
            AuthorizationInfo info = null;
            if (log.isTraceEnabled()) {
                log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
            }
            Cache<Object, AuthorizationInfo> cache = this.getAvailableAuthorizationCache();
            Object key;
            if (cache != null) {
                if (log.isTraceEnabled()) {
                    log.trace("Attempting to retrieve the AuthorizationInfo from cache.");
                }
                key = this.getAuthorizationCacheKey(principals);
                info = (AuthorizationInfo)cache.get(key);
                if (log.isTraceEnabled()) {
                    if (info == null) {
                        log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
                    } else {
                        log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
                    }
                }
            }
            if (info == null) {
                info = this.doGetAuthorizationInfo(principals);
                if (info != null && cache != null) {
                    if (log.isTraceEnabled()) {
                        log.trace("Caching authorization info for principals: [" + principals + "].");
                    }

                    key = this.getAuthorizationCacheKey(principals);
                    cache.put(key, info);
                }
            }
            return info;
        }
}

 它是將String類型的url 封裝成了 Permission對象型的 url,然後調用過程,請看上面的代碼調用,大概說一下流程:先去看是否有緩存機制,如果有,則去緩存裏找一找AuthorizationInfo(注意,這個info裏面是包含了用戶所擁有的全部權限url ,是個集合),如果找到了,那就直接用這個info,將我們要授權驗證的那個url去這個info中匹配,看是否info中包含了這個url,如果包含了,則返回true,授權驗證通過,如果沒有包含,則返回false,授權驗證失敗。 那如果沒有緩存機制的話,就去調用我們自定義Realm中的doGetAuthorizationInfo( )方法,所以重點來了(我們在自定義Realm的doGetAuthorizationInfo( ) 方法中,就應該將用戶的全部權限查出來——從數據庫查,封裝在info中,再返回)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章