目錄
授權三要素
授權方法
授權順序
ModularRealmAuthorizer
PermissionResolver和RolePermissionResolver
WildcardPermission的規則簡單介紹如下:
授權三要素
授權具有三個在Shiro中引用的核心元素:權限,角色和使用者
權限:比如公司給你提供辦公電腦,你可以使用該電腦,你的同僚不能使用,但你不能将此電腦賣了換錢。(權限就是對某個資源的處理權。處理權分多種,這裡就是使用和變賣)
角色:在公司來說,員工就是角色,上司也是角色,他不是具體的某個人,可以隻某個崗位(研發、測試、産品),或者是某個部門(組織部、研發部),角色就是代表一類使用者,在授權中,角色就是代表擁有某些共同權限的一類使用者。
使用者:使用者是使用系統的使用者,一般情況下,使用者與角色綁定,角色與權限綁定,那麼該使用者擁有哪些權限自然就知道了。
三者的簡單關系:一個使用者可以擁有多個角色,一個角色擁有多個權限。有些系統可能角色和權限一起使用或者沒有角色,直接将權限賦予使用者。
授權方法
我們使用subject類的如下方法來進行權限認證:
- boolean isPermitted(String var1);
- 是否有某個權限
- boolean isPermitted(Permission var1);
- boolean[] isPermitted(String... var1);
- 傳回是否有對應權限的數組
- boolean[] isPermitted(List<Permission> var1);
- 同上
- boolean isPermittedAll(String... var1);
- 是否擁有清單中的所有權限
- boolean isPermittedAll(Collection<Permission> var1);
- 同上
- void checkPermission(String var1) throws AuthorizationException;
- 是否擁有權限(如果沒有将抛出AuthorizationException異常)下同,依此類推
- void checkPermission(Permission var1) throws AuthorizationException;
- void checkPermissions(String... var1) throws AuthorizationException;
- void checkPermissions(Collection<Permission> var1) throws AuthorizationException;
- boolean hasRole(String var1);
- boolean[] hasRoles(List<String> var1);
- boolean hasAllRoles(Collection<String> var1);
- void checkRole(String var1) throws AuthorizationException;
- void checkRoles(Collection<String> var1) throws AuthorizationException;
- void checkRoles(String... var1) throws AuthorizationException;
總結:has*方法,驗證失敗将傳回false,而check*方法,驗證失敗将抛出AuthorizationException異常。實際使用中根據情況選用,大部分是使用check*方法讓他抛出異常。
基于注釋的授權
基于注解的授權需要你的程式是支援AOP的,我們常見的是在Spring的AOP架構下使用
RequiresAuthentication
注解
RequiresAuthentication
調用被該注解修飾的方法時,subject是已認證的,其等效于SecurityUtils.getSubject().isAuthenticated() == true
@RequiresAuthentication
public void updateAccount(Account userAccount) {
//需要是已認證的Subject才能調用該方法
...
}
RequiresGuest
注解
RequiresGuest
允許遊客通路
@RequiresGuest
public void signUp(User newUser) {
//允許遊客通路
...
}
其等效于如下代碼:
Subject currentUser = SecurityUtils.getSubject();
PrincipalCollection principals = currentUser.getPrincipals();
if (principals != null && !principals.isEmpty()) {
throw new AuthorizationException(...);
}
RequiresPermissions
注解
RequiresPermissions
允許某個或某些權限通路
RequiresRoles注解
RequiresRoles注解
允許某個或某些角色通路
RequiresUser
注解
RequiresUser
允許已知身份的使用者通路(
Subject
具有已知身份的,該身份是由于在目前會話期間進行了身份驗證而已知的,或者是從先前會話的“ RememberMe”服務中記住的)
關于注解的使用示例,我們将在後面的shiro的web內建中展示。此處了解即可。
授權順序
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL9EFSlxGdtJGc412Y2plMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3YzM1QDO1MTMwEzMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
- 步驟1:應用程式或架構Subject所有如下方法( hasRole*,checkRole*,isPermitted*,或checkPermission*方法變體)進行權限或角色的授權驗證。
- 步驟2:一般情況下,程式中的Subject是DelegatingSubject(或其子類)調用上面的方法時,實際上是使用的SecurityManager的hasRole*,checkRole*,isPermitted*,或checkPermission*方法變體(securityManager而實作了org.apache.shiro.authz.Authorizer接口,hasRole*,checkRole*,isPermitted*,或checkPermission*方法變體這些方法是Authorizer接口的定義)。
- 步驟3:在我們使用SecurityManager時。Authorizer接口預設實作是ModularRealmAuthorizer,該執行個體是一個執行個體,它支援Realm在任何授權操作期間協調一個或多個執行個體。
- 步驟4:Realm檢查每個已配置的配置,以檢視是否實作了相同的Authorizer接口。如果是這樣,ModularRealmAuthorizer調用該領域的各自的hasRole*,checkRole*,isPermitted*,或checkPermission*方法被調用。
總結:從上我們可以了解到,所有的認證權限的方法,最終都是調用的Realm中對應的hasRole*,checkRole*,isPermitted*,或checkPermission*方法
ModularRealmAuthorizer
上面我們提到,ModularRealmAuthorizer是Authorizer接口的預設實作,而且我們的SecurityManager也預設使用它,它來協調執行每個配置好的Realm。它的執行規則如下:
- 如果Realm自身實作Authorizer接口,其各自的Authorizer對應的方法(hasRole*,checkRole*,isPermitted*,或checkPermission*)被調用。
- 如果Realm的方法導緻異常,則将抛出AuthorizationException異常給Subject調用方。這會縮短授權過程,并且該授權操作将不再執行任何剩餘的領域。
- 如果Realm的方法是傳回布爾值的hasRole*或isPermitted*變體,并且傳回值是true,則該true值将立即傳回,并且所有剩餘的Realms都将不再執行。
- 如果Realm不實作該Authorizer接口,則将其忽略。
PermissionResolver和RolePermissionResolver
Resolver顧名思義,就是權限和角色的解析器(預設情況下,我們的權限或角色我們都直接通過字元串的形式進行表示,如果你需要自定義其他方式,或其他的解析方式,就需要使用這兩個接口來實作--建議是使用預設方式就夠了)
這兩個接口都會将我們提供的角色或權限的字元串解析為Permission對象,Permission對象的預設實作是WildcardPermission,WildcardPermission定義了權限字元串的解析方式和定義規則。
一般情況下,我們的Realm會實作PermissionResolverAware和RolePermissionResolverAware兩個接口,這兩個接口提供了PermissionResolver和RolePermissionResolver的設定,如果我們自定義Resolver的話,就需要使用realm的對應的set方法進行設定。
WildcardPermission的規則簡單介紹如下:
單個權限表示:query
多級的權限表示:
- test:query:我們可以用test來表示菜單,query表示操作,該權限表示擁有test菜的的query操作權限
- a:test:query:更多級的權限表示
"*"的使用:
- test:*:表示我們可以使用test菜單下的所有操作(該權限表示包含了test:query權限)
上一篇:003-認證
下一篇:005-shiro的Realm源碼解析與自定義Realm