Apache Shiro權限框架理論介紹

Apache Shiro權限管理框架介紹

Apache Shiro的官網地址如下:

http://shiro.apache.org/

Apache Shiro是一個簡單易用且強大而靈活的開源Java安全框架,以下簡稱Shiro。它乾淨利落地處理身份認證、授權以及企業會話管理和加密。Shiro擁有易於理解的API,你可以快速且容易地使用它來保護任何應用程序——從最小的移動應用程序到最大的web和企業應用程序。

Shiro權限基礎概念:

  • 安全實體:就是被權限系統保護的對象,比如工資數據。  
  • 權限:就是需要被校驗的行爲,比如查看、修改等。
  • 分配權限:把對某些安全實體的某些權限分配給某些人員。是向數據庫裏面添加數據、或是維護數據的過程
  • 權限驗證(權限匹配):判斷某個人員或程序對某個安全實體是否擁有某個或某些權限。從數據庫中獲取相應數據進行匹配的過程。
  • 權限的繼承性:如果多個安全實體存在包含關係,而某個安全實體沒有權限限制,則它會繼承包含它的安全實體的相應權限。
  • 權限的最近匹配原則:如果多個安全實體存在包含關係,而某個安全實體沒有權限限制,那麼它會向上尋找並匹配相應權限限制,直到找到一個離這個安全實體最近的擁有相應權限限制的安全實體爲止。如果把整個層次結構都尋找完了都沒有匹配到相應權限限制的話,那就說明所有人對這個安全實體都擁有這個相應的權限限制。

Shiro 能做什麼:

  • 認證:驗證用戶的身份
  • 授權:對用戶執行訪問控制:判斷用戶是否被允許做某事
  • 管理:在任何環境下使用 Session API,即使沒有 Web 或EJB 容器。
  • 加密:以更簡潔易用的方式使用加密功能,保護或隱藏數據防止被偷窺
  • Realms:聚集一個或多個用戶安全數據的數據源
  • 單點登錄(SSO)功能:爲沒有關聯到登錄的用戶啓用 "Remember Me“ 服務

Shiro 的主要功能架構圖:

Apache Shiro權限框架理論介紹

從上圖中可以看到 Shiro 的四大核心部分:

  • Authentication(身份驗證):簡稱爲“登錄”,即證明用戶是誰。
  • Authorization(授權):訪問控制的過程,即決定是否有權限去訪問受保護的資源。
  • Session Management(會話管理):管理用戶特定的會話,即使在非 Web 或 EJB 應用程序。
  • Cryptography(加密):通過使用加密算法保持數據安全

其中 Shiro 還提供了以下擴展:

  • Web Support:主要針對web應用提供一些常用功能。
  • Caching:緩存可以使應用程序運行更有效率。
  • Concurrency:多線程相關功能。
  • Testing:幫助我們進行測試相關功能
  • "Run As":一個允許用戶假設爲另一個用戶身份(如果允許)的功能,有時候在管理腳本很有用。
  • "Remember Me" :記住用戶身份,提供類似購物車功能。

Shiro 概念層架構的 3 個核心組件圖:

Apache Shiro權限框架理論介紹

  • Subject :正與系統進行交互的人,或某一個第三方服務。所有 Subject 實例都被綁定到(且這是必須的)一個SecurityManager 上。
  • SecurityManager:Shiro 架構的心臟,用來協調內部各安全組件,管理內部組件實例,並通過它來提供安全管理的各種服務。當 Shiro 與一個 Subject 進行交互時,實質上是幕後的 SecurityManager 處理所有繁重的Subject 安全操作,可以將其概念比作爲是SpringMVC中的前端控制器。
  • Realms :本質上是一個特定安全的 DAO。當配置 Shiro 時,必須指定至少一個 Realm 用來進行身份驗證或授權。Shiro 提供了多種可用的 Realms 來獲取安全相關的數據。如關係數據庫(JDBC),INI 及屬性文件等。可以定義自己 Realm 實現來代表自定義的數據源。

Shiro 架構圖:

Apache Shiro權限框架理論介紹

  • Authenticator :執行對用戶的身份驗證(登錄)的組件。Authenticator 從一個或多個 Realm 中獲得數據以驗證用戶的身份。 若存在多個realm,則接口 AuthenticationStrategy 會確定什麼樣算是驗證成功(例如,如果一個 Realm 成功,而其他的均失敗,是否登錄成功)。
  • Authorizer :權限管理器,主要用於用戶的訪問控制,驗證用戶能否訪問應用中的受保護資源。
  • SessionManager :session管理器,可在任何應用或架構層一致地使用 Session API
  • SessionDAO:SessionManager 執行 Session 持久化(CRUD)操作。
  • CacheManager :對 Shiro 組件提供緩存支持。
  • Cryptography:Shiro 的 API 大幅度簡化 Java API 中繁瑣的密碼加密
  • Realms:Shiro 通過 Realms 來獲取相應的安全數據

Shiro 配置基礎

Shiro 被設計成能夠在任何環境下工作,從簡單的命令行應用程序到企業羣集應用。由於環境的多樣性,使得 Shiro 可以使用多種配置機制。

users:

  • ini 配置:ini 實際上是一個文本配置,包含了由唯一命名的項來組織的鍵/值對。
  • [users] 部分允許定義一組靜態的用戶帳戶
  • 每行的格式:username = password, roleName1, roleName2, …

roles:

  • [roles] 部分允許把定義在 [users] 部分中的角色與權限關聯起來
  • 每行的格式:rolename = permissionDefinition1, permissionDefinition2, …
    • permissionDefinition 是一個任意的字符串,但大多數人將會使用符合 org.apache.shiro.authz.permission.WildcardPermission 格式的字符串。

注意:

  • 如果一個獨立的 permissionDefinition 需要被內部逗號分隔(例如,printer:5thFloor:print,info),則需要用戶雙引號環繞該定義,以避免錯誤解析。  
  • 如果角色不想關聯權限,則不需要在 [roles] 部分把它們列出來。只需定義在 [user] 部分中定義角色名就足以創建尚不存在的角色。
  • 僅定義非空的 [users] 或 [roles] 部分就將自動地觸發org.apache.shiro.realm.text.IniRealm 實例的創建

Shiro 身份認證: Authentication

Authentication :身份驗證——通過提交用戶的身份和憑證給 Shiro,以判斷它們是否和應用程序預期的相匹配。

基本概念:

  • Principals(身份):Subject 的 identifying attributes(標識屬性)。比如我們登錄提交的用戶名。
  • Credentials(憑證):用來作爲一種起支持作用的證據,此證據包含×××明。比如我們登錄提供的密碼

認證的基本步驟:

  • 收集Subjects 提交的Principals(身份)和Credentials(憑證);
  • 提交Principals(身份)和Credentials(憑證)進行身份驗證;
  • 如果提交成功,則允許訪問,否則重新進行身份驗證或者阻止訪問。
  • AuthenticationToken:Shiro 中代表提交的 Principals(身份) 和 Credentials (憑證) 的身份驗證系統的最基本接口。
  • UsernamePasswordToken :AuthenticationToken 的接口的實現類,支持最常見的用戶名/密碼的身份驗證

提交用戶名/密碼進行認證:

Subject currentUser = SecurityUtils.getSubject();
currentUser.login(token);

處理認證成功和失敗

  • 認證成功:沒有返回,也沒有異常,通過。
  • 認證失敗,拋出異常,可以在程序中捕獲並處理

認證順序:
Apache Shiro權限框架理論介紹

認證過程:
Apache Shiro權限框架理論介紹

Step 1:應用程序代碼調用 Subject.login 方法,傳遞創建好的包含終端用戶的 Principals(身份)和 Credentials(憑證)的 AuthenticationToken 實例

Step 2:Subject 實例,通常爲 DelegatingSubject(或子類)委託應用程序的 SecurityManager 通過調用 securityManager.login(token) 開始真正的驗證。

Step 3:SubjectManager 接收 token,調用內部的 Authenticator 實例調用 authenticator.authenticate(token)。 Authenticator 通常是一個 ModularRealmAuthenticator 實例,支持在身份驗證中協調一個或多個Realm 實例。

Step 4:如果應用程序中配置了一個以上的 Realm,ModularRealmAuthenticator 實例將利用配置好的AuthenticationStrategy 來啓動 Multi-Realm 認證嘗試。在Realms 被身份驗證調用之前,期間和以後,AuthenticationStrategy 被調用使其能夠對每個Realm 的結果作出反應。

Step 5:每個配置的 Realm 用來幫助看它是否支持提交的AuthenticationToken。如果支持,那麼支持 Realm 的 getAuthenticationInfo 方法將會伴隨着提交的 token 被調用。getAuthenticationInfo 方法有效地代表一個特定 Realm 的單一的身份驗證嘗試。


Shiro 授權

授權:又稱訪問控制—控制誰有權限在應用程序中做什麼。在授權中,需要了解幾個關鍵的對象:Subject 主體、Resource 資源、Permissions 權限、Role 角色:

  • Subject 主體:訪問應用的用戶,在 Shiro 中使用 Subject 代表該用戶,用戶需要授權後才能訪問相應的資源
  • Resource 資源:在應用中用戶訪問的任何東西,例如:jsp、接口、圖片等,都屬於是資源
  • Permissions 權限:Shiro 安全機制最核心的元素。它在應用程序中明確聲明瞭被允許的行爲。一個格式良好的權限聲明可以清晰表達出用戶對該資源擁有的權限。在 Shiro 中主要通過通配符表達式來完成權限的描述
  • Role 角色:一個命名的實體, 通常代表一組行爲或職責。 這些行爲演化爲在一個應用中能或者不能做的事情。角色通常分配給用戶帳戶。一個角色擁有一個權限的集合。授權驗證時,需要判斷當前角色是否擁有指定的權限。這種角色權限可以對該角色進行詳細的權限描述。 Shiro官方推薦使用這種方式

授權檢查的例子:用戶是否能訪問某個網頁,編輯數據,或打使用這臺打印機

授權的三要素:權限、角色和用戶 。

需要在應用程序中對用戶和權限建立關聯:通常的做法是將權限分配給角色,然後將角色分配給一個或多個用戶。

Shiro的三種授權方式:

  • 編寫代碼:在 Java 代碼中用像 if 和 else 塊的結構執行授權檢查。
  • JDK 的註解:可以添加授權註解給 Java 方法
  • JSP 標籤庫:可以控制基於角色和權限的JSP 頁面輸出。

Shiro 授權順序圖:
Apache Shiro權限框架理論介紹

時序圖:
Apache Shiro權限框架理論介紹

  • Step 1:應用程序或框架代碼調用任何 Subject 的hasRole*, checkRole*, isPermitted*,或者checkPermission*方法的變體,傳遞任何所需的權限
  • Step 2:Subject 的實例—通常是 DelegatingSubject(或子類),調用securityManager 的對應的方法。
  • Step 3:SecurityManager 調用 org.apache.shiro.authz.Authorizer 接口的對應方法。默認情況下,authorizer 實例是一個 ModularRealmAuthorizer 實例,它支持協調任何授權操作過程中的一個或多個Realm 實例。
  • Step 4:每個配置好的 Realm 被檢查是否實現了相同的 Authorizer 接口。如果是,Realm 各自的 hasRole*, checkRole*, isPermitted*,或 checkPermission* 方法將被調用。

Shiro 基礎語法:Permissions的聲明方式

基礎語法之簡單的字符串:

  • 即用簡單的字符串來表示一個權限,如:user (相當於:user:*

基礎語法之多層次管理:

  • 例如:user:query、user:edit
  • 多個值:每個部件能夠保護多個值。因此,除了授予用戶 user:queryuser:edit 權限外,也可以簡單地授予他們一個:user:query, edit
  • 還可以用 * 號代替所有的值,如:user:* , 也可以寫:*:query,表示某個用戶在所有的領域都有 query 的權限

基礎語法之實例級訪問控制:

  • 這種情況通常會使用三個部件:域、操作、被付諸實施的實例。如:user:edit:manager
  • 也可以使用通配符來定義,如:user:edit:*、user:*:*、user:*:manager
  • 部分省略通配符:缺少的部件意味着用戶可以訪問所有與之匹配的值,比如:user:edit 等價於 user:edit :*、user 等價於 user:*:*

注意:通配符只能從字符串的結尾處省略部件,也就是說 user:edit 並不等價於 user:*:edit


Shiro 註銷

logout(註銷):currentUser.logout();

  • 調用 logout() 方法時,現有 Session 將失效,而且身份將失去關聯(在Web 應用程序中,RememberMe cookie 將被刪除)。
  • 在 Subject 註銷後,該 Subject 的實例被再次認爲是匿名的。

注意:WEB 應用程序記住身份往往依靠 Cookie,然而Cookie 只能在 Response 被返回後被刪除,所以建議在調用subject.logout() 後立即向終端重定向一個新的視圖或頁面。這樣即能保證與安全相關的 Cookie 都能像預期的一樣被刪除。


Realm

  • Realm:訪問應用程序安全數據(如用戶、角色及權限)的組件。
  • Realm 通常和數據源是一對一的對應關係,如關係數據庫、文件系統或其他類似資源。Realm 實質上就是一個訪問安全數據的 DAO。
  • 數據源通常存儲身份驗證數據(如密碼的憑證)以及授權數據(如角色或權限),所以每個Realm 都能夠執行身份驗證和授權操作。

Realms的認證實現

Shiro 的認證過程由 Realm 執行,SecurityManager 會調用 org.apache.shiro.realm.RealmgetAuthenticationInfo(AuthenticationToken token) 方法

實際開發中,通常會提供 org.apache.shiro.realm.AuthenticatingRealm 的實現類,並在該實現類中提供doGetAuthenticationInfo(AuthenticationToken token)方法的具體實現

  1. 檢查提交的進行認證的令×××信息
  2. 根據令×××信息從數據源(通常爲數據庫)中獲取用戶信息
  3. 對用戶信息進行匹配驗證。
  4. 驗證通過將返回一個封裝了用戶信息的 AuthenticationInfo 實例。
  5. 驗證失敗則拋出 AuthenticationException 異常信息。

Shiro權限攔截

Shiro和Spring Security一樣,都是基於過濾器來實現權限攔截的。shiro中默認的過濾器:
Apache Shiro權限框架理論介紹

過濾器鏈:
Apache Shiro權限框架理論介紹

過濾器類圖:
Apache Shiro權限框架理論介紹


Shiro會話管理

Shiro提供了完整的企業級會話管理功能,不依賴於底層容器(如Tomcat),不管是J2SE還是J2EE環境都可以使用,提供了會話管理,會話事件監聽,會話存儲/持久化,容器無關的集羣,失效/過期支持,對Web的透明支持,SSO單點登錄的支持等特性。

建議在開發中,Controller層使用原生的HttpSession對象,在Service層中使用Shiro提供的Session對象。如果在Service層中使用HttpSession對象,那麼屬於侵入式,並不建議這麼做。Shiro提供的Session能夠很好的解決這個問題。

會話管理相關類圖:
Apache Shiro權限框架理論介紹


Shiro權限緩存

緩存是×××能的重要手段,對同一批數據進行多次查詢時, 第一次查詢走數據庫,查詢數據後,將數據保存在內存中,第二次以後查詢可以直接從內存獲取數據,從而不需要和數據庫進行交互。這樣減少了系統查詢數據庫的次數,提升了性能。

緩存適合那些經常不變動的數據,比如系統中用戶的信息和權限不會經常改變,特別適合緩存起來供下次使用。其中我們的權限信息就是不怎麼會改變的,對權限信息進行緩存可以提高我們系統的性能。不過 Shiro 自身不實現緩存,而是提供緩存接口,讓其他第三方實現,默認支持EhCache和MapCache緩存。

Shiro 緩存相關的類圖:
Apache Shiro權限框架理論介紹

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章