Apache Shiro權限框架理論介紹

Apache Shiro權限管理框架介紹

Apache Shiro的官網地址以下:前端

http://shiro.apache.org/java

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

Shiro權限基礎概念:算法

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

Shiro 能作什麼:數據庫

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

Shiro 的主要功能架構圖:

Apache Shiro權限框架理論介紹

從上圖中能夠看到 Shiro 的四大核心部分:apache

  • 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:cookie

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

roles:session

  • [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權限框架理論介紹