1. 程式人生 > >shiro簡單理解

shiro簡單理解

1.shiro所能做的事情
  • 驗證使用者來核實他們的身份
  • 對使用者執行訪問控制,
    • 如:判斷使用者是否被分配了一個確定的安全形色
      • 判斷使用者是否被允許做某事
  • 在任何環境下使用 Session API,即使沒有 Web 或 EJB 容器
  • 在身份驗證,訪問控制期間或在會話的生命週期,對事件作出反應。
  • 聚集一個或多個使用者安全資料的資料來源,並作為一個單一的複合使用者“檢視”。
  • 啟用單點登入(SSO)功能。
  • 為沒有關聯到登入的使用者啟用"Remember Me"服務
2.shiro 重要概念(1)shiro架構圖
(2)概念(來自中文文件)
  • Subject(org.apache.shiro.subject.Subject) 當前與軟體進行互動的實體(使用者,第三方服務,cron job,等等)的安全特定“檢視”。
  • SecurityManager(org.apache.shiro.mgt.SecurityManager) 如上所述,SecurityManager 是 Shiro 架構的心臟。它基本上是一個“保護傘”物件,協調其管理的元件以確保 它們能夠一起順利的工作。它還管理每個應用程式使用者的 Shiro 的檢視,因此它知道如何執行每個使用者的安全 操作。
  • Authenticator(org.apache.shiro.authc.Authenticator) Authenticator 是一個對執行及對使用者的身份驗證(登入)嘗試負責的元件。當一個使用者嘗試登入時,該邏輯 被 Authenticator 執行。Authenticator 知道如何與一個或多個 Realm 協調來儲存相關的使用者/帳戶資訊。從這些 Realm 中獲得的資料被用來驗證使用者的身份來保證使用者確實是他們所說的他們是誰。
    • Authentication Strategy(org.apache.shiro.authc.pam.AuthenticationStrategy) 如果不止一個 Realm 被配置,則 AuthenticationStrategy 將會協調這些 Realm 來決定身份認證嘗試成功或 失敗下的條件(例如,如果一個 Realm 成功,而其他的均失敗,是否該嘗試成功? 是否所有的 Realm 必須成功?或只有第一個成功即可?)。
  • Authorizer(org.apache.shiro.authz.Authorizer) Authorizer 是負責在應用程式中決定使用者的訪問控制的元件。它是一種最終判定使用者是否被允許做某事的機制。 與 Authenticator 相似,Authorizer 也知道如何協調多個後臺資料來源來訪問角色惡化許可權資訊。Authorizer 使用 該資訊來準確地決定使用者是否被允許執行給定的動作。
  • SessionManager(org.apache.shiro.session.SessionManager) SessionManager 知道如何去建立及管理使用者 Session 生命週期來為所有環境下的使用者提供一個強健的 Session 體驗。這在安全框架界是一個獨有的特色——Shiro 擁有能夠在任何環境下本地化管理使用者 Session 的能力, 即使沒有可用的 Web/Servlet 或 EJB 容器,它將會使用它內建的企業級會話管理來提供同樣的程式設計體驗。 SessionDAO 的存在允許任何資料來源能夠在持久會話中使用。
    • SessionDAO(org.apache.shiro.session.mgt.eis.SessionDAO) SesssionDAO 代表 SessionManager 執行 Session 持久化(CRUD)操作。這允許任何資料儲存被插入到會 話管理的基礎之中。
  • CacheManager(org.apahce.shiro.cache.CacheManager) CacheManager 建立並管理其他 Shiro 元件使用的 Cache 例項生命週期。因為 Shiro 能夠訪問許多後臺資料來源, 由於身份驗證,授權和會話管理,快取在框架中一直是一流的架構功能,用來在同時使用這些資料來源時提高 效能。任何現代開源和/或企業的快取產品能夠被插入到 Shiro 來提供一個快速及高效的使用者體驗。
  • Cryptography(org.apache.shiro.crypto.*) Cryptography 是對企業安全框架的一個很自然的補充。Shiro 的 crypto 包包含量易於使用和理解的cryptographic Ciphers,Hasher(又名 digests)以及不同的編碼器實現的代表。所有在這個包中的類都被精心地設計以易於 使用和易於理解。任何使用 Java 的本地密碼支援的人都知道它可以是一個難以馴服的具有挑戰性的動物。Shiro 的 cryptoAPI 簡化了複雜的 Java 機制,並使加密對於普通人也易於使用。
  • Realms(org.apache.shiro.realm.Realm) 如上所述,Realms 在 Shiro 和你的應用程式的安全資料之間擔當“橋樑”或“聯結器”。當它實際上與安全 相關的資料如用來執行身份驗證(登入)及授權(訪問控制)的使用者帳戶互動時,Shiro 從一個或多個為應用 程式配置的 Realm 中尋找許多這樣的東西。你可以按你的需要配置多個 Realm(通常一個數據源一個 Realm), 且 Shiro 將為身份驗證和授權對它們進行必要的協調。
3.身份驗證(1)流程
(2)分析1.獲得subject
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject=SecurityUtils.getSubject();
subject.login(token);
這裡的token是一個包含使用者身份Principals(賬號)與憑證Credentials(密碼)的AuthenticationToken例項,一般我們用UsernamePasswordToken token=new UsernamePasswordToken(account,password);,注:PrincipalsCredentials這兩個單詞會在shiro中頻繁出現。
try { subject.login(token);//會丟擲的異常
} catch ( UnknownAccountException uae ) { …
} catch ( IncorrectCredentialsException ice ) { …
} catch (LockedAccountException lae ) { …
} catch (ExcessiveAttemptsException eae ) { …
} … catch your own …
} catch ( AuthenticationException ae ) {
 //unexpected error?
}


2.呼叫subject.login(token)後,委託應用程式的 SecurityManager, SecurityManager通過呼叫 securityManager.login(token)開始真正的驗證工作,SecurityManager 提供了一個安全的環境3.SecurityManager 接收 token 以及簡單地委託給內部的 Authenticator 例項通過呼叫 authenticator.authenticate(token),實際上SecurityManager 宣告為
public interface SecurityManager extends Authenticator, Authorizer, SessionManager 
4.如果應用程式中配置了一個以上的 Realm(realm概念見上),ModularRealmAuthenticator 例項將利用配置好的 AuthenticationStrategy 來啟動 Multi-Realm 認證嘗試。在 Realms 被身份驗證呼叫之前,期間和以後, AuthenticationStrategy 呼叫使其能夠對每個 Realm 的結果作出反應,另外AuthenticationStrategy 負責從每一個成功的 Realm 彙總結果並將它們“捆綁”到一個單一的 AuthenticationInfo 再現。這最後彙總的 AuthenticationInfo 例項就是從 Authenticator 例項返回的值。AuthenticationStrategy 有3個具體實現
  AtLeastOneSuccessfulStrategy 如果一個(或更多)Realm 驗證成功,則整體的嘗試被認為是成功的。如果沒有一個驗證成功,則整體嘗試失敗。  
 FirstSuccessfulStrategy   只有第一個成功地驗證的 Realm 返回的資訊將被使用。所有進一步的 Realm 將被忽略。如果沒有一個驗證成功,則整體嘗試失敗。
  AllSucessfulStrategy 為了整體的嘗試成功,所有配置的 Realm 必須驗證成功。如果沒有一個驗證成功,則整體嘗試失敗。

         5.配置Realm來對token進行校驗,看它是否支援提交的 AuthenticationToken。如果支援,那麼支援 Realm 的getAuthenticationInfo 方法將會伴隨著提交的 token 被呼叫。

            通常自定義Realm通過繼承AuthorizingRealm並重寫其中的兩個方法,如

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserMapper userMapper;
    //許可權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
    //驗證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String account=(String)authenticationToken.getPrincipal();
        User user=userMapper.selectUserByAccount(account);
        //這裡不需要丟擲異常
        if(user==null){
            throw new UnknownAccountException("未知使用者名稱");
        }
        //這裡是從資料庫查出的密碼
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(account,user.getCpassword(),"userRealm");
        info.setCredentialsSalt(ByteSource.Util.bytes(Const.ShiroConst.SALT));
        return info;
    }
}

4.授權


(待更新)