Shiro 是一個強大而靈活的開源安全框架,可以很是清晰的處理認證、受權、管理會話以及密碼加密。以下是它所具備的特色:html
易於理解的 Java Security API;web
簡單的身份認證(登陸),支持多種數據源(LDAP,JDBC,Kerberos,ActiveDirectory 等);apache
對角色的簡單的籤權(訪問控制),支持細粒度的籤權;緩存
支持一級緩存,以提高應用程序的性能;安全
內置的基於 POJO 企業會話管理,適用於 Web 以及非 Web 的環境;session
異構客戶端會話訪問;架構
很是簡單的加密 API;框架
不跟任何的框架或者容器捆綁,能夠獨立運行。工具
首先,咱們來看看的 Shiro 的總體架構,見下圖:性能
圖 1. 總體架構
從上圖能夠看出,Shiro 主要有四個組件:
SecurityManager
典型的 Facade,Shiro 經過它對外提供安全管理的各類服務。
Authenticator
對「Who are you ?」進行覈實。一般涉及用戶名和密碼。
這個組件負責收集 principals 和 credentials,並將它們提交給應用系統。若是提交的 credentials 跟應用系統中提供的 credentials 吻合,就可以繼續訪問,不然須要從新提交 principals 和 credentials,或者直接終止訪問。
Authorizer
身份份驗證經過後,由這個組件對登陸人員進行訪問控制的篩查,好比「who can do what」, 或者「who can do which actions」。Shiro 採用「基於 Realm」的方法,即用戶(又稱 Subject)、用戶組、角色和 permission 的聚合體。
Session Manager
這個組件保證了異構客戶端的訪問,配置簡單。它是基於 POJO/J2SE 的,不跟任何的客戶端或者協議綁定。
圖 2. 安全模型
上圖中,涉及了 Shiro 的五個概念:
Subject 是安全領域術語,除了表明人,它還能夠是應用。在單應用中,可將其視爲 User 的同義詞。
Principal 是 Subject 的標識,通常狀況下是惟一標識,好比用戶名。
Role 和 Permission 分別表明了不一樣粒度的權限,從上圖中能夠看出 Role 的粒度更大些,Permission 表明了系統的原子權限,好比數據的修改、刪除權限。對於簡單的權限應用,能夠不須要 Permission。
Realm 是一個執行者,負責真正的認證和鑑權。
實現應用的安全模塊的關鍵在於:定義合適的 role 和 permission,這就須要遵循以下原則:
role 沒有實質內容,只是表明一組 permission,目的是爲了管理的方便,通常都是動態定義;
permission 通常都是預先定義好的,不容許動態改變,除非源代碼改動,它纔會變化,它是整個安全模塊的基礎;
要使 permission 也能動態定義,並不是不可能,可是這將使鑑權很是複雜,甚至可能致使鑑權語句遍及整個程序,得不償失;
固然有一個例外:若是知道 permission 動態定義的規則和鑑權規則,如 Grails 的 fileter 中「${controllerName}:${actionName}:${params.id}」也可實現 permission 的動態定義
圖 3. 關鍵類
AuthenticationToken 和 AuthenticationInfo
前者在認證前使用,描述認證所需的信息,最經常使用的就是 username 和 password 對;後者在認證後使用,內容同前,可是表示已經通過認證的信息。
RememberMe
表明的是一種可能狀態,並不表示該 Subject 已經通過了認證。對於一些普通的操做,這種可能狀態並沒有大礙,但一旦涉及安全敏感的操做,必須通過認證。
Credentials 和 CredentialsMatcher
Credentials 是 Subject 的證書,在認證時使用,最經常使用的就是 password。在一般狀況下,爲了安全起見,Subject 的 credentials 都須要加密保存,因而 CredentialsMatcher 的做用就體現出來了,見下圖:
這裏 CredentialsMatcher 須要將加密後的證書跟用戶登陸時提供的證書進行比對,完成認證的過程。
PAM= Pluggable Authentication Modules
在有多個 Realm 的時候使用。由認證策略決定認證結果,即 PAM= Relams + 認證策略。通常的策略有 3 種:AllSuccessful、AtLeastOneSuccessful 和 FirstSuccessful。
AuthorizationInfo
能夠當作是 Role + Permission 的組合體。
PermissionResolver 和 Permission
它們之間的關係以下:
在 Shiro 中,權限被轉化爲一種字符串描述(字符串分級表示,稱之爲 WildcardPermission),從而將權限轉化爲相似於對象 equals 的操做(Shiro 中的 implies 方法)。
內置的權限有 2 個:
AllPermission,老是返回 true
WildcardPermission,權限字符串的表示方式。
WildcardPermission 是 Shiro 的精妙之處,咱們能夠將權限表示成字符串,這樣對權限的控制能夠不拘泥於物理存儲,好比對 messagge 類具備修改和刪除權限能夠標識爲:message:update,delete:*,其中‘ * ’表示全部;第一級分隔符爲‘ : ’;第二級分隔符爲‘ , ’,而對於權限字符串的解釋徹底能夠由應用本身來定。
若是要比較權限字符串,可使用 permission1.implies(permission2),它分別比較對應位置的字符串,在以下狀況中,結果會返回 true:
permission1 中的子串有 * 或 permission1 子串 ==permission2 子串;
permission1 無子串,permission2 有;
permission1 有子串,permission2 無,permission1 的全部子串都是 *。
總的說來,Shiro 中的 Permission 須要注意以下內容:
權限的比較實際是字符串的比較,只不過是考慮到了字符串的分級
字符串的分級劃分徹底由使用者本身決定,Shiro 的慣例是 3 級:資源 : 操做 : 實例。
字符串的使用必須一致,分隔符之間不要有空格,避免無心間引入的不一致。如:定義使用「file : create, update : 1」,而驗證使用「file : update」,那麼分解以後一個是「 update 」,一個是「 update」,因空格而引發不等。
Realm
這是一個實際訪問安全實體的組件,通常是應用相關的,跟數據源的關係是 1-1。它負責完成認證和鑑權,getAuthenticationInfo 表明了 login 的嘗試,鑑權方法則由 Authorizer 繼承而來。此處也體現了 Shiro 代碼的另外一個特色,經過繼承來擴充功能。以經常使用的 JdbcRealm 爲例,其繼承鏈以下:
Session
它關聯一個 Subject 的上下文,其做用相似於在 HttpSession 中保存用戶標識,session 一旦過時,則從新登陸。Shiro 的 Session 是獨立的,其目的是作到環境無關性。爲了利用 Web 環境中,Shiro 實現了一個直接使用 HttpSession 的 WebSession。
SecurityManager
這是一個 Façade 接口,=Authenticator + Authorizer + SessionFactory。在總體框架圖中已經看到了它在 Shiro 中所處的位置。其特色同 Realm,同樣是使用繼承不斷地擴充功能。對於 Web 應用通常使用 DefaultWebSecurityManager。
Filter
在 Web 環境下使用 filter 進行認證和權限檢查是毋庸置疑的,而 Shiro 的特色則在於由一個主 Filter 將一羣子 filter 串起來:
在實際使用時,須注意:
web.xml 中只需配置 org.apache.shiro.web.servlet.ShiroFilter和EnvironmentLoaderListener。對於 Spring 應用,則使用 DelegatingFilterProxy;
子 filter 做爲主 filter 的配置參數值出現,特色是:順序相關
對於多個 URL,驗證順序是由上至下,相似 Exception 的匹配。所以,使用順序應該是由細到粗。
對於同一 URL,子 filter 的驗證順序是從左至右的 AND 操做。
若是配置值中含有分隔符,如 Permission,就須要使用引號來轉義。
Subject
subject 表明了一個用戶的狀態和操做,它提供了全部安全相關的操做,包括認證和籤權。能夠將其視爲另外一種形式的 Façade。缺省實現是將這些操做委派給其內部包含的 SecurityManager。
Configuration
configuration 負責將全部這些組件串起來,最終建立 SecurityManager。在 Shiro 中,缺省格式是 ini。整個配置關係以下圖:
JSecurityFilter 建立 Configuration 實例,並將 ini 參數值傳給 Configuation。在 Spring 環境中,分別使用 SpringJSecurityFilter 和 SpringIniWebConfiguration。
Configuration 實際就是 SecurityManager 的 Factroy,對 SpringIniWebConfiguration 而言,它須要知道 SecurityManager 的 BeanName,該值由 SpringJSecurityFilter 的初始化參數「securityManagerBeanName」值決定。即 SpringJSecurityFilter,實際有兩個初始化參數:
config,是 ini 配置文件內容
securityManagerBeanName,是 SecurityManager 的 BeanName
SecurityUtils
這是 Shiro 中最重要的工具類,由它能夠方便地得到 Subject 和 SecurityManager。
雜項
AOP,提供 AOP 方面的支持,實現對某個類某個方法的攔截,從而使權限控制延伸至類的方法。
Cache,提供緩存支持
Codec,提供編碼方面的支持
Crypto,提供加密支持
IO,從多個資源位置讀寫原始數據
JNDI,提供 jndi 支持
util,工具類支持
標籤類,用於 Web 頁面
經常使用標籤:
principal, 輸出當前用戶的標識
hasRole,判斷當前用戶是否屬於給定的角色,參數:name
hasPermission, 判斷當前用戶是否具備指定的權限,參數:type,action 或者 permission
isLoggedIn, 判斷當前用戶是否已經登陸
hasAnyRole,判斷當前用戶是否屬於給定的某個角色,參數:in
下面是本身整理的圖
http://www.cnblogs.com/dairongle/archive/2012/02/14/2350668.html