1. 程式人生 > >第六章 Realm及相關物件——《跟我學Shiro》

第六章 Realm及相關物件——《跟我學Shiro》

ection;然後通過其getPrimaryPrincipal獲取PrimaryPrincipal。

Java程式碼  收藏程式碼
  1. Set<String> realmNames = princialCollection.getRealmNames();  

獲取所有身份驗證成功的Realm名字。      

Java程式碼  收藏程式碼
  1. Set<Object> principals = princialCollection.asSet(); //asList和asSet的結果一樣  

將身份資訊轉換為Set/List,即使轉換為List,也是先轉換為Set再完成的。

Java程式碼  收藏程式碼
  1. Collection<User> users = princialCollection.fromRealm("c");  

根據Realm名字獲取身份,因為Realm名字可以重複,所以可能多個身份,建議Realm名字儘量不要重複。

6.4 AuthorizationInfo

AuthorizationInfo用於聚合授權資訊的:

Java程式碼  收藏程式碼
  1. public interface AuthorizationInfo extends Serializable {  
  2.     Collection<String> getRoles(); //獲取角色字串資訊  
  3.     Collection<String> getStringPermissions(); //獲取許可權字串資訊
      
  4.     Collection<Permission> getObjectPermissions(); //獲取Permission物件資訊  
  5. }   

當我們使用AuthorizingRealm時,如果身份驗證成功,在進行授權時就通過doGetAuthorizationInfo方法獲取角色/許可權資訊用於授權驗證。

Shiro提供了一個實現SimpleAuthorizationInfo,大多數時候使用這個即可。

對於Account及SimpleAccount,之前的【6.3 AuthenticationInfo】已經介紹過了,用於SimpleAccountRealm子類,實現動態角色/許可權維護的。

6.5 Subject

Subject是Shiro的核心物件,基本所有身份驗證、授權都是通過Subject完成。

1、身份資訊獲取

Java程式碼  收藏程式碼
  1. Object getPrincipal(); //Primary Principal  
  2. PrincipalCollection getPrincipals(); // PrincipalCollection   

2、身份驗證

Java程式碼  收藏程式碼
  1. void login(AuthenticationToken token) throws AuthenticationException;  
  2. boolean isAuthenticated();  
  3. boolean isRemembered();  

通過login登入,如果登入失敗將丟擲相應的AuthenticationException,如果登入成功呼叫isAuthenticated就會返回true,即已經通過身份驗證;如果isRemembered返回true,表示是通過記住我功能登入的而不是呼叫login方法登入的。isAuthenticated/isRemembered是互斥的,即如果其中一個返回true,另一個返回false。

3、角色授權驗證 

Java程式碼  收藏程式碼
  1. boolean hasRole(String roleIdentifier);  
  2. boolean[] hasRoles(List<String> roleIdentifiers);  
  3. boolean hasAllRoles(Collection<String> roleIdentifiers);  
  4. void checkRole(String roleIdentifier) throws AuthorizationException;  
  5. void checkRoles(Collection<String> roleIdentifiers) throws AuthorizationException;  
  6. void checkRoles(String... roleIdentifiers) throws AuthorizationException;   

hasRole*進行角色驗證,驗證後返回true/false;而checkRole*驗證失敗時丟擲AuthorizationException異常。 

4、許可權授權驗證

Java程式碼  收藏程式碼
  1. boolean isPermitted(String permission);  
  2. boolean isPermitted(Permission permission);  
  3. boolean[] isPermitted(String... permissions);  
  4. boolean[] isPermitted(List<Permission> permissions);  
  5. boolean isPermittedAll(String... permissions);  
  6. boolean isPermittedAll(Collection<Permission> permissions);  
  7. void checkPermission(String permission) throws AuthorizationException;  
  8. void checkPermission(Permission permission) throws AuthorizationException;  
  9. void checkPermissions(String... permissions) throws AuthorizationException;  
  10. void checkPermissions(Collection<Permission> permissions) throws AuthorizationException;  

isPermitted*進行許可權驗證,驗證後返回true/false;而checkPermission*驗證失敗時丟擲AuthorizationException。

5、會話

Java程式碼  收藏程式碼
  1. Session getSession(); //相當於getSession(true)  
  2. Session getSession(boolean create);    

類似於Web中的會話。如果登入成功就相當於建立了會話,接著可以使用getSession獲取;如果create=false如果沒有會話將返回null,而create=true如果沒有會話會強制建立一個。

6、退出 

Java程式碼  收藏程式碼
  1. void logout();  

7、RunAs  

Java程式碼  收藏程式碼
  1. void runAs(PrincipalCollection principals) throws NullPointerException, IllegalStateException;  
  2. boolean isRunAs();  
  3. PrincipalCollection getPreviousPrincipals();  
  4. PrincipalCollection releaseRunAs();   

RunAs即實現“允許A假設為B身份進行訪問”;通過呼叫subject.runAs(b)進行訪問;接著呼叫subject.getPrincipals將獲取到B的身份;此時呼叫isRunAs將返回true;而a的身份需要通過subject. getPreviousPrincipals獲取;如果不需要RunAs了呼叫subject. releaseRunAs即可。

8、多執行緒

Java程式碼  收藏程式碼
  1. <V> V execute(Callable<V> callable) throws ExecutionException;  
  2. void execute(Runnable runnable);  
  3. <V> Callable<V> associateWith(Callable<V> callable);  
  4. Runnable associateWith(Runnable runnable);   

實現執行緒之間的Subject傳播,因為Subject是執行緒繫結的;因此在多執行緒執行中需要傳播到相應的執行緒才能獲取到相應的Subject。最簡單的辦法就是通過execute(runnable/callable例項)直接呼叫;或者通過associateWith(runnable/callable例項)得到一個包裝後的例項;它們都是通過:1、把當前執行緒的Subject繫結過去;2、線上程執行結束後自動釋放。

Subject自己不會實現相應的身份驗證/授權邏輯,而是通過DelegatingSubject委託給SecurityManager實現;及可以理解為Subject是一個面門。

對於Subject的構建一般沒必要我們去建立;一般通過SecurityUtils.getSubject()獲取:

Java程式碼  收藏程式碼
  1. public static Subject getSubject() {  
  2.     Subject subject = ThreadContext.getSubject();  
  3.     if (subject == null) {  
  4.         subject = (new Subject.Builder()).buildSubject();  
  5.         ThreadContext.bind(subject);  
  6.     }  
  7.     return subject;  
  8. }   

即首先檢視當前執行緒是否綁定了Subject,如果沒有通過Subject.Builder構建一個然後繫結到現場返回。

如果想自定義建立,可以通過:

Java程式碼  收藏程式碼
  1. new Subject.Builder().principals(身份).authenticated(true/false).buildSubject()  

這種可以建立相應的Subject例項了,然後自己繫結到執行緒即可。在new Builder()時如果沒有傳入SecurityManager,自動呼叫SecurityUtils.getSecurityManager獲取;也可以自己傳入一個例項。

對於Subject我們一般這麼使用:

1、身份驗證(login)

2、授權(hasRole*/isPermitted*或checkRole*/checkPermission*)

3、將相應的資料儲存到會話(Session)

4、切換身份(RunAs)/多執行緒身份傳播

5、退出

而我們必須的功能就是1、2、5。到目前為止我們就可以使用Shiro進行應用程式的安全控制了,但是還是缺少如對Web驗證、Java方法驗證等的一些簡化實現。