跟我學Shiro——身份認證(2)

Shiro 身份驗證

身份驗證,即在應用中誰能證實他就是他本人。通常提供如他們的身份 ID 一些標識信息來代表他就是他本人,如提供身份證,用戶名 / 密碼來證實。web

在 shiro 中,用戶須要提供 principals (身份)和 credentials(證實)給 shiro,從而應用能驗證用戶身份:spring

principals:身份,即主體的標識屬性,能夠是任何東西,如用戶名、郵箱等,惟一便可。一個主體能夠有多個 principals,但只有一個 Primary principals,通常是用戶名 / 密碼 / 手機號。數據庫

credentials:證實 / 憑證,即只有主體知道的安全值,如密碼 / 數字證書等。apache

最多見的 principals 和 credentials 組合就是用戶名 / 密碼了。接下來先進行一個基本的身份認證。安全

另外兩個相關的概念是以前提到的 Subject 及 Realm,分別是主體及驗證主體的數據源。測試

環境準備編碼

本文使用 Maven 構建,所以須要一點 Maven 知識。首先準備環境依賴:加密

<dependency>
 <groupId>org.apache.shiro</groupId>
 <artifactId>shiro-spring</artifactId>
 <version>1.3.2</version>
 </dependency>

登陸 / 退出spa

一、首先準備一些用戶身份 / 憑據(shiro.ini)(此處的ini文件其實能夠認爲是數據庫,真正的項目多是從數據庫中讀出來的)線程

image

此處使用 ini 配置文件,經過 [users] 指定了兩個主體:admin/admin、張三/123465。

二、測試用例

@Test
    public void testHelloworld() {
        //一、獲取SecurityManager工廠,此處使用Ini配置文件初始化SecurityManager
        Factory<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();
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin");
        try {
            //四、登陸,即身份驗證
            subject.login(token);
            System.out.println("登錄成功");
        } catch (AuthenticationException e) {
            //五、身份驗證失敗
        }
        Assert.assertEquals(true, subject.isAuthenticated()); //斷言用戶已經登陸
        //六、退出
        subject.logout();
    }

image

  1. 首先經過 new IniSecurityManagerFactory 並指定一個 ini 配置文件來建立一個 SecurityManager 工廠;

  2. 接着獲取 SecurityManager 並綁定到 SecurityUtils,這是一個全局設置,設置一次便可;

  3. 經過 SecurityUtils 獲得 Subject,其會自動綁定到當前線程;***若是在 web 環境在請求結束時須要解除綁定;而後獲取身份驗證的 Token,如用戶名 / 密碼;

4. 調用 subject.login 方法進行登陸,其會自動委託給 SecurityManager.login 方法進行登陸;

若是身份驗證失敗請捕獲 AuthenticationException 或其子類,常見的如: DisabledAccountException(禁用的賬號)、LockedAccountException(鎖定的賬號)、UnknownAccountException(錯誤的賬號)、ExcessiveAttemptsException(登陸失敗次數過多)、IncorrectCredentialsException (錯誤的憑證)、ExpiredCredentialsException(過時的憑證)等,具體請查看其繼承關係;對於頁面的錯誤消息展現,最好使用如 「用戶名 / 密碼錯誤」 而不是 「用戶名錯誤」/「密碼錯誤」,防止一些惡意用戶非法掃描賬號庫;

最後能夠調用 subject.logout 退出,其會自動委託給 SecurityManager.logout 方法退出。

從如上代碼可總結出身份驗證的步驟

  1. 收集用戶身份 / 憑證,即如用戶名 / 密碼;

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

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

如上測試的幾個問題:

  • 用戶名 / 密碼硬編碼在 ini 配置文件,之後須要改爲如數據庫存儲,且密碼須要加密存儲;
  • 用戶身份 Token 可能不只僅是用戶名 / 密碼,也可能還有其餘的,如登陸時容許用戶名 / 郵箱 / 手機號同時登陸。

    身份認證流程


    流程以下
  1. 首先調用 Subject.login(token) 進行登陸,其會自動委託給 Security Manager,調用以前必須經過 SecurityUtils.setSecurityManager() 設置;
  2. SecurityManager 負責真正的身份驗證邏輯;它會委託給 Authenticator 進行身份驗證;
  3. Authenticator 纔是真正的身份驗證者,Shiro API 中核心的身份認證入口點,此處能夠自定義插入本身的實現;
  4. Authenticator 可能會委託給相應的 AuthenticationStrategy 進行多 Realm 身份驗證,默認 ModularRealmAuthenticator 會調用 AuthenticationStrategy 進行多 Realm 身份驗證;
  5. Authenticator 會把相應的 token 傳入 Realm,從 Realm 獲取身份驗證信息,若是沒有返回 / 拋出異常表示身份驗證失敗了。此處能夠配置多個 Realm,將按照相應的順序及策略進行訪問。
相關文章
相關標籤/搜索