shiro身份認證流程

首先要理解兩個概念:Subject和Realm,分別是主體及驗證主體的數據源。web

身份驗證步驟以下:數據庫

一、收集用戶身份/憑證,即如用戶名/密碼。apache

(1)web項目配置web.xml,再經過如下語句便可得到用戶身份/憑證。spa

Subject subject = SecurityUtils.getSubject();

(2)非web項目則獲取用戶身份/憑證以下:code

//一、獲取SecurityManager工廠,此處使用Ini配置文件初始化SecurityManager
        Factory<org.apache.shiro.mgt.SecurityManager> factory =
          new IniSecurityManagerFactory("classpath:shiro.ini");
        //二、獲得SecurityManager實例 並綁定給SecurityUtils
        org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        //三、獲得Subject及建立用戶名/密碼身份驗證Token(即用戶身份/憑證)
        Subject subject = SecurityUtils.getSubject();

二、調用Subject.login進行登陸,若是失敗將獲得相應的AuthenticationException異常,根據異常提示用戶錯誤信息;不然登陸成功。xml

輸入圖片說明

(1)調用Subject.login(token)進行登陸,這裏的token是須要與數據源進行驗證的身份及憑證,調用的login方法是Subject接口的實現類DelegatingSubject裏的方法,這個方法又委託給接口SecurityManage, SecurityManage經過實現類DefaultSecurityManager的login方法實現。到這裏,咱們知道這個login方法實際執行的是DefaultSecurityManager的login方法。繼承

(2)須要驗證的數據取到了,那麼問題來了,如今怎麼與數據庫裏或.Ini文件裏的正確身份/憑證進行驗證呢。token

DefaultSecurityManager類的login方法調用了authenticate方法,這個方法來源有點複雜。首先、DefaultSecurityManager經過層層繼承,最後繼承了抽象類AuthenticatingSecurityManager。如圖:接口

輸入圖片說明

AuthenticatingSecurityManager實現了Authenticator,Authenticator有個實現類叫作AbstractAuthenticator,以下圖。圖片

輸入圖片說明

因此咱們AuthenticatingSecurityManager調用的authenticate方法實現實際來源於AbstractAuthenticator,如圖:

輸入圖片說明

AbstractAuthenticator繼續調用ModularRealmAuthenticator裏的方法doAuthenticate,可進行多Realm身份驗證,如圖,

輸入圖片說明

protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws      AuthenticationException {
        assertRealmsConfigured();
        Collection<Realm> realms = getRealms();
        if (realms.size() == 1) {
            return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
        } else {
            return doMultiRealmAuthentication(realms, authenticationToken);
        }
    }

最後doMultiRealmAuthentication調用了咱們以前實現的Realm裏的getAuthenticationInfo方法,Authenticator會把相應的token傳入Realm,從Realm獲取身份驗證信息,若是沒有返回/拋出異常表示身份驗證失敗了。此處能夠配置多個Realm,將按照相應的順序及策略進行訪問

三、最後調用Subject.logout進行退出操做。

相關文章
相關標籤/搜索