初識Shiro

Shiro是Apache的一個權限管理框架,鑑於不少人對權限管理的概念都不是很清楚,因此我在正式介紹Shiro前我會談談權限管理的概念。前端

1.權限管理

1.1什麼是權限管理

只要有用戶參與的系統通常都要有權限管理,權限管理實現對用戶訪問系統的控制,按照安全規則或者安全策略控制用戶能夠訪問並且只能訪問本身被受權的資源。權限管理包括用戶認證用戶受權兩部分java

1.2用戶認證

用戶認證,用戶去訪問系統,系統要驗證用戶身份的合法性。最經常使用的用戶身份驗證的方法:一、用戶名密碼方式。二、指紋打卡機。三、基於證書驗證方法。只有當系統驗證用戶身份合法,用戶纔可訪問系統的資源。web

1.2.1用戶認證流程

1.2.2關鍵對象

subject:主體,理解爲用戶,多是程序、網絡爬蟲等,都要去訪問系統的資源,系統須要對subject進行身份認證。spring

principal:身份信息,一般是惟一的,一個主體還有多個身份信息,可是都有一個主身份信息(primary principal)。數據庫

credential:憑證信息,能夠是密碼 、證書、指紋。緩存

總結:主體在進行身份認證時須要提供身份信息和憑證信息。安全

1.3用戶受權

用戶受權,簡單理解爲訪問控制,在用戶認證經過後(注意只有當用戶認證經過後才能對用戶進行受權),系統對用戶訪問資源進行控制,用戶具備資源的訪問權限方可訪問。服務器

1.3.1受權流程

1.3.2關鍵對象

受權的過程理解爲:who對what(which)進行how操做。網絡

who:主體即subject,subject在認證經過後系統進行訪問控制。多線程

what(which):資源(Resource),subject必須具有資源的訪問權限纔可訪問該 資源。資源好比:系統用戶列表頁面、商品修改菜單、商品id爲001的商品信息。資源分爲資源類型和資源實例:系統的用戶信息就是資源類型,至關於java類;系統中id爲001的用戶就是資源實例,至關於new的java對象。

how:權限/許可(permission) ,針對資源的權限或許可,subject具備permission訪問資源,如何訪問/操做須要定義permission,權限好比:用戶添加、用戶修改、商品刪除。

1.3.3權限模型

對1.3.2節提到的主體、資源、權限經過數據模型表示,標準權限數據模型包括 :用戶(帳號和密碼)、角色(角色名稱)、權限(包括資源和權限)、用戶角色關係(用戶id、角色id)、角色權限關係(角色id、權限id)。以下圖:

而一般企業開發中將資源表和權限表合併爲一張權限表,以下圖:

上圖常被稱爲權限管理的通用模型,不過企業在開發中根據系統自身的特色還會對上圖進行修改,可是用戶、角色、權限、用戶角色關係、角色權限關係是須要去理解的。

1.3.4分配權限

用戶須要分配相應的權限纔可訪問相應的資源。權限是對於資源的操做許可。

一般給用戶分配資源權限須要將權限信息持久化,好比存儲在關係數據庫中。

把用戶信息、權限管理、用戶分配的權限信息寫到數據庫(權限數據模型)。

1.3.5權限控制(受權的核心)

權限的控制分爲基於角色的訪問控制和基於資源的訪問控制。

基於角色的訪問控制:RBAC((role based access control)。好比:系統角色包括 :部門經理、總經理。(角色針對用戶來劃分)。

系統代碼中的實現爲:

1
2
3
4
5
//若是該user是部門經理則能夠訪問if中的代碼
if(user.hasRole('部門經理')){
	//系統資源內容
	//用戶報表查看
}

 

基於角色的訪問控制出現的問題:角色針對人劃分的,人做爲用戶在系統中屬於活動內容,若是該 角色能夠訪問的資源出現變動,須要修改你的代碼了,好比:須要變動爲部門經理和總經理均可以進行用戶報表查看,代碼改成:

1
2
3
4
if(user.hasRole('部門經理') || user.hasRole('總經理')  ){
	//系統資源內容
	//用戶報表查看
}

 

可知基於角色的訪問控制是不利於系統維護(可擴展性不強)。

而對於基於資源的訪問控制:RBAC(Resource based access control)。由於資源在系統中是不變的,好比資源有:類中的方法,頁面中的按鈕。對資源的訪問須要具備permission權限,代碼能夠寫爲:

1
2
3
4
if(user.hasPermission ('用戶報表查看(權限標識符)')){
	//系統資源內容
	//用戶報表查看
}

 

上邊的方法就能夠解決用戶角色變動不用修改上邊權限控制的代碼。若是須要變動權限只須要在分配權限模塊去操做,給部門經理或總經理增或刪除權限。因此在實際開發中咱們建議使用基於資源的訪問控制實現權限管理。

1.4權限管理解決方案

1.4.1什麼是粗粒度和細粒度權限

粗粒度權限管理:對資源類型的權限管理。資源類型好比:菜單、url鏈接、用戶添加頁面、用戶信息、類方法、頁面中按鈕。粗粒度權限管理好比:超級管理員能夠訪問戶添加頁面、用戶信息等所有頁面。部門管理員能夠訪問用戶信息頁面包括 頁面中全部按鈕。

細粒度權限管理:對資源實例的權限管理。資源實例就資源類型的具體化,好比:用戶id爲001的修改鏈接,1110班的用戶信息、行政部的員工。細粒度權限管理就是數據級別的權限管理。細粒度權限管理好比:部門經理只能夠訪問本部門的員工信息,用戶只能夠看到本身的菜單,大區經理只能查看本轄區的銷售訂單。

粗粒度和細粒度例子:系統有一個用戶列表查詢頁面,對用戶列表查詢分權限,若是粗顆粒管理,張三和李四都有用戶列表查詢的權限,張三和李四均可以訪問用戶列表查詢。
進一步進行細顆粒管理,張三(行政部)和李四(開發部)只能夠查詢本身本部門的用戶信息。張三隻能查看行政部 的用戶信息,李四隻能查看開發部門的用戶信息。細粒度權限管理就是數據級別的權限管理。

1.4.2如何實現粗粒度和細粒度權限管理

如何實現粗粒度權限管理?

粗粒度權限管理比較容易將權限管理的代碼抽取出來在系統架構級別統一處理。好比:經過springmvc的攔截器實現受權。

如何實現細粒度權限管理?

對細粒度權限管理在數據級別是沒有共性可言,針對細粒度權限管理就是系統業務邏輯的一部分,若是在業務層去處理相對比較簡單,若是將細粒度權限管理統一在系統架構級別去抽取,比較困難,即便抽取的功能可能也存在擴展不強。

建議細粒度權限管理在業務層去控制。好比:部門經理只查詢本部門員工信息,在service接口提供一個部門id的參數,controller中根據當前用戶的信息獲得該 用戶屬於哪一個部門,調用service時將部門id傳入service,實現該用戶只查詢本部門的員工。

2.什麼是Shiro

Apache Shiro是Java的一個權限管理框架,相比Spring框架中的權限管理框架Spring Security,Spring Security和Spring的依賴過於緊密,沒有Shiro使用簡單,並且Shiro不依賴Spring,它不只能夠實現web應用的權限管理,還能夠實現c/s系統、分佈式系統權限管理。

Shiro屬於輕量框架,能夠幫助咱們完成:認證、受權、加密、會話管理、與Web集成、緩存等功能,因此愈來愈多企業項目開始使用Shiro。並且Shiro的API也是很是簡單,其基本功能點以下圖:

解釋:

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

記住一點:Shiro不會去維護用戶、維護權限,這些須要咱們本身去設計/提供;而後經過相應的接口注入給Shiro便可。

接下來咱們分別從外部和內部來看看Shiro的架構,對於一個好的框架,從外部來看應該具備很是簡單易於使用的API,且API契約明確;從內部來看的話,其應該有一個可擴展的架構,即很是容易插入用戶自定義實現,由於任何框架都不能知足全部需求。

3.Shiro架構

3.1從外部看Shiro架構

從外部看Shiro,即從應用程序的角度來觀察如何使用Shiro完成工做。以下圖Apache官網爲咱們提供的一張Shiro的架構圖:

解釋:應用代碼直接交互的對象是Subject,也就是說Shiro的對外API核心就是Subject;圖中每一個API的含義:

  • Subject:主體,表明了當前「用戶」,這個用戶不必定是一個具體的人,與當前應用交互的任何東西都是Subject,如網絡爬蟲,機器人等;即一個抽象概念;全部Subject都綁定到SecurityManager,與Subject的全部交互都會委託給SecurityManager;能夠把Subject認爲是一個門面;SecurityManager纔是實際的執行者。
  • SecurityManager:安全管理器;即全部與安全有關的操做都會與SecurityManager交互;且它管理着全部Subject;能夠看出它是Shiro的核心,它負責與後邊介紹的其餘組件進行交互,若是學習過SpringMVC,你能夠把它當作DispatcherServlet前端控制器。
  • Realm:域,Shiro從從Realm獲取安全數據(如用戶、角色、權限),就是說SecurityManager要驗證用戶身份,那麼它須要從Realm獲取相應的用戶進行比較以肯定用戶身份是否合法;也須要從Realm獲得用戶相應的角色/權限進行驗證用戶是否能進行操做;能夠把Realm當作DataSource,即安全數據源。

也就是說對於咱們而言,最簡單的一個Shiro應用都是通過以下步驟:

一、應用代碼經過Subject來進行認證和受權,而Subject又委託給SecurityManager。

二、咱們須要給Shiro的SecurityManager注入Realm,從而讓SecurityManager能獲得合法的用戶及其權限進行判斷。

從以上也能夠看出,Shiro不提供維護用戶/權限,而是經過Realm讓開發人員本身注入。

3.2從內部看Shiro架構

架構圖以下:

分析:

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