首先要理解兩個概念: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進行退出操做。