Shiro01 功能點框圖、架構圖、身份認證邏輯、身份認證代碼實現

基本功能點

功能點框圖

功能點說明

一、Authentication:身份認證/登陸,驗證用戶是否是擁有相應的身份;
二、Authorization:受權,即權限驗證,驗證某個已認證的用戶是否擁有某個權限;即判斷用戶是否能作事情,常見的如:驗證某個用戶是否擁有某個角色。或者細粒度的驗證某個用 戶對某個資源是否具備某個權限;
三、SessionManager:會話管理,即用戶登陸後就是一次會話,在沒有退出以前,它的全部信 息都在會話中;會話能夠是普通 JavaSE 環境的,也能夠是如 Web 環境的;
四、Cryptography:加密,保護數據的安全性,如密碼加密存儲到數據庫,而不是明文存儲;
五、Web Support:Web 支持,能夠很是容易的集成到 Web 環境;
六、Caching:緩存,好比用戶登陸後,其用戶信息、擁有的角色/權限沒必要每次去查,這樣能夠提升效率;
七、Concurrency:shiro支持多線程應用的併發驗證,即如在一個線程中開啓另外一個線程,能 把權限自動傳播過去;
八、Testing:提供測試支持;
九、Run As:容許一個用戶僞裝爲另外一個用戶(若是他們容許)的身份進行訪問;
十、RememberMe:記住我,這個是很是常見的功能,即一次登陸後,下次再來的話不用登陸了。
十一、注意:Shiro 不會去維護用戶、維護權限;這些須要咱們本身去設計/提供;而後經過 相應的接口注入給 Shiro 便可。 前端

外部架構圖

一、架構圖
web

二、架構說明
2.一、應用代碼直接交互的對象是Subject, 也就是說Shiro的對外API核心就是Subject;
2.二、應用代碼經過 Subject 來進行認證和受權,而 Subject 又委託給 SecurityManager;
2.三、咱們須要給 Shiro 的 SecurityManager 注入 Realm,從而讓 SecurityManager 能獲得合法 的用戶及其權限進行判斷。
三、API說明
3.一、Subject:主體,表明了當前「用戶」,這個用戶不必定是一個具體的人,與當前應用交互 的任何東西都是 Subject,如網絡爬蟲,機器人等;即一個抽象概念;全部 Subject 都綁定 到 SecurityManager,與 Subject 的全部交互都會委託給 SecurityManager;能夠把 Subject 認 爲是一個門面;SecurityManager 纔是實際的執行者;
3.二、SecurityManager:安全管理器;即全部與安全有關的操做都會與 SecurityManager 交互; 且它管理着全部 Subject;能夠看出它是 Shiro 的核心,它負責與後邊介紹的其餘組件進行 交互,若是學習過 SpringMVC,你能夠把它當作 DispatcherServlet 前端控制器;
3.三、Realm:域,Shiro 從從 Realm 獲取安全數據(如用戶、角色、權限),就是說 SecurityManager 要驗證用戶身份,那麼它須要從 Realm 獲取相應的用戶進行比較以肯定用戶身份是否合法;也須要從 Realm 獲得用戶相應的角色/權限進行驗證用戶是否能進行操做;能夠把 Realm 看 成 DataSource,即安全數據源。
4 注意:Shiro 不提供維護用戶/權限,而是經過 Realm 讓開發人員本身注入。 數據庫

內部架構圖

一、架構圖
apache

二、模塊說明
2.一、Subject:主體,能夠看到主體能夠是任何能夠與應用交互的「用戶」;
2.二、SecurityManager : 至關於 SpringMVC 中 的 DispatcherServlet 或者 Struts2 中 的 FilterDispatcher;是 Shiro 的心臟;全部具體的交互都經過 SecurityManager 進行控制;它管 理着全部 Subject、且負責進行認證和受權、及會話、緩存的管理。
2.三、Authenticator:認證器,負責主體認證的,這是一個擴展點,若是用戶以爲 Shiro 默認的 很差,能夠自定義實現;其須要認證策略(Authentication Strategy),即什麼狀況下算用戶 認證經過了;
2.四、Authrizer:受權器,或者訪問控制器,用來決定主體是否有權限進行相應的操做;即控制 着用戶能訪問應用中的哪些功能;
2.五、Realm:能夠有1個或多個Realm,能夠認爲是安全實體數據源,即用於獲取安全實體的;能夠是JDBC實現,也能夠是LDAP實現,或者內存實現等等;由用戶提供;注意:Shiro不知道你的用戶權限存儲在哪及以何種格式存儲;因此咱們通常在應用中都須要實現本身的Realm;
2.六、SessionManager:若是寫過 Servlet 就應該知道 Session 的概念,Session 呢須要有人去管理 它的生命週期,這個組件就是 SessionManager;而ShiroWeb環境,也 能夠用在如普通的 JavaSE環境、EJB等環境;全部呢Shiro就抽象了一個本身的Session來管理主體與應用之間交互的數據;這樣的話,好比咱們在 Web 環境用,剛開始是一臺 Web 服務器;接着又上了臺EJB服務器;這時想把兩臺服務器的會話數據放到一個地方, 這個時候就能夠實現本身的分佈式會話(如把數據放到 Memcached 服務器);
2.七、SessionDAO:DAO 你們都用過,數據訪問對象,用 於 會話的 CRUD,好比咱們想把 Session保存到數據庫,那麼能夠實現本身的SessionDAO,經過如JDBC寫到數據庫;好比想把 Session 放到 Memcached中,能夠實現本身的MemcachedSessionDAO;另外SessionDAO 中可使用 Cache 進行緩存,以提升性能;
2.八、CacheManager:緩存控制器,來管理如用戶、角色、權限等的緩存的;由於這些數據基本 上不多去改變,放到緩存中後能夠提升訪問的性能;
2.九、Cryptography:密碼模塊,Shiro 提升了一些常見的加密組件用於如密碼加密/解密的。 緩存

身份認證

特殊名詞

一、身份驗證:即在應用中誰能證實他就是他本人。通常提供如他們的身份 ID 一些標識信息來 代表他就是他本人,如提供身份證,用戶名/密碼來證實。 在 shiro 中,用戶須要提供 principals (身份)和 credentials(證實)給 shiro,從而應用能 驗證用戶身份:
二、principals:身份,即主體的標識屬性,能夠是任何東西,如用戶名、郵箱等,惟一便可。 一個主體能夠有多個 principals,但只有一個 Primary principals,通常是用戶名/密碼/手機號。
三、credentials:證實/憑證,即只有主體知道的安全值,如密碼/數字證書等。 最多見的 principals 和 credentials 組合就是用戶名/密碼了。接下來先進行一個基本的身份認 證。
四、另外兩個相關的概念是以前提到的Subject及Realm,分別是主體及驗證主體的數據源。安全

認證邏輯(使用IniRealm)

一、經過一個ini文件來建立Realm
二、接着獲取 SecurityManager 並將Realm綁定到SecurityManager;
三、將SecurityManager綁定到 SecurityUtils,這是一個全局設置,設置一次便可;
四、經過 SecurityUtils 獲得 Subject,其會自動綁定到當前線程;若是在 web 環境在請求結 束時須要解除綁定;而後獲取身份驗證的 Token,如用戶名/密碼;
五、調用 subject.login 方法進行登陸,其會自動委託給 SecurityManager.login 方法進行登陸;
六、若是身份驗證失敗請捕獲 AuthenticationException 或 其 子類,常見的如: DisabledAccountException(禁用的賬號)、LockedAccountException(鎖定的賬號)、 UnknownAccountException(錯誤的賬號)、ExcessiveAttemptsException(登陸失敗次數過 多)、IncorrectCredentialsException(錯誤的憑證)、ExpiredCredentialsException(過時的憑證)等,具體請查看其繼承關係;對於頁面的錯誤消息展現,最好使用如「用戶名/密碼 錯誤」而不是「用戶名錯誤」/「密碼錯誤」,防止一些惡意用戶非法掃描賬號庫;
七、最後能夠調用 subject.logout 退出,其會自動委託給 SecurityManager.logout 方法退出。服務器

代碼實現

一、建立一個Maven工程,不一樣的maven工程便可,不須要時web工程
二、引入junit、shiro依賴網絡

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

三、在resources目錄下建立一個shiro.ini文件
3.一、項目目錄結構
多線程

3.二、shiro.ini內容架構

[users]
fury=111111
zeus=222222

4 測試類

package com.xunyji.shirotest.kaitao;

import jdk.nashorn.internal.parser.Token;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * @author AltEnter
 * @create 2019-01-17 14:58
 * @desc 認證
 **/
public class TestDemo01 {

    @Test
    public void testDemo01() {
//        01 建立Realm
        IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
//        02 建立SecurityManager並將Realm設置到SecurityManager中
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(iniRealm);

//        03 將SecurityManager設置到SecurityUtils中
        SecurityUtils.setSecurityManager(defaultSecurityManager);
//        04 從SecurityUtils中獲取Subject
        Subject subject = SecurityUtils.getSubject();
//        05 將用戶名和用戶密碼封裝成一個Token
        UsernamePasswordToken token = new UsernamePasswordToken("fury", "111111");
//        06 經過Subject進行登陸認證
        subject.login(token);
//        07 經過Subject判斷登陸認證結果
        System.out.println(String.format("用戶名fury和密碼111111的用戶的認證結果爲:%s", subject.isAuthenticated()));
    } 

}

認證總結

一、認證步驟
1.一、收集用戶身份/憑證,即如用戶名/密碼;
1.二、調用 Subject.login 進行登陸,若是失敗將獲得相應的 AuthenticationException 異常,根 據異常提示用戶錯誤信息;不然登陸成功;
1.三、最後調用 Subject.logout 進行退出操做。
二、改進方案
2.一、用戶名和密碼硬編碼在ini配置文件,之後須要改爲如數據庫存儲,且密碼須要加密存儲;
2.二、用戶身份Token可能不只僅是用戶名和密碼,也可能還有其餘的,如登陸時容許用戶名/ 郵箱/手機號同時登陸。
三、認證流程
3.一、流程圖
認證外部流程圖:

認證內部流程圖:

3.二、首先調用 Subject.login(token)進行登陸,其會自動委託給 Security Manager,調用以前必 須經過 SecurityUtils. setSecurityManager()設置; 還須要爲SecurityManager設置Realm;
3.三、SecurityManager 負責真正的身份驗證邏輯;它會委託給 Authenticator 進行身份驗證;
3.四、Authenticator纔是真正的身份驗證者,ShiroAPI中核心的身份認證入口點,此處能夠自 定義插入本身的實現;
3.五、Authenticator可能會委託給相應的AuthenticationStrategy進行多Realm身份驗證,默認 ModularRealmAuthenticator 會調用 AuthenticationStrategy 進行多 Realm 身份驗證;
3.六、Authenticator會把相應的token傳入Realm,從Realm獲取身份驗證信息,若是沒有返 回和拋出異常表示身份驗證失敗了。此處能夠配置多個Realm,將按照相應的順序及策略進 行訪問。
四、技巧:從subject.login(token)往下查看源碼就能夠清楚地知道整個登陸認證流程

相關文章
相關標籤/搜索