序言
大家好,我是老馬。
shiro 還有其他優秀的特性,今天我們就一起來學習一下,為後續深入學習奠定基礎。
Apache Shiro 是什麼?Apache Shiro 是一種功能強大且易於使用的Java安全框架,它執行身份驗證,授權,加密和會話管理,可用於保護任何應用程式的安全-從命令列應用程式,移動應用程式到最大的Web和企業應用程式。
shiro 的元件結構如下圖:
components
Shiro提供了應用程式安全性API來執行以下方面(我喜歡將它們稱為應用程式安全性的4個基石):
身份驗證-證明使用者身份,通常稱為使用者“登入”。授權-訪問控制密碼學-保護或隱藏資料以防窺視會話管理-每個使用者的時間敏感狀態Shiro還支援一些輔助功能,例如Web應用程式安全性,單元測試和多執行緒支援,但是這些功能可以增強上述四個主要方面。
特性您可以使用Apache Shiro進行以下操作:
驗證使用者身份以驗證其身份對使用者執行訪問控制,例如:確定是否為使用者分配了特定的安全形色確定是否允許使用者做某事即使在沒有Web或EJB容器的情況下,也可以在任何環境中使用Session API。在身份驗證,訪問控制或會話的生存期內對事件做出反應。彙總1個或更多使用者安全資料的資料來源,並將其全部顯示為單個複合使用者“檢視”。啟用單點登入(SSO)功能啟用“記住我”服務以進行使用者關聯,而無需登入為什麼要使用 Apache Shiro?自2003年以來,框架環境發生了很大變化,因此今天仍然有充分的理由使用Shiro。
Apache Shiro 優勢如下:
易於使用-易於使用是該專案的最終目標。應用程式安全性可能非常令人困惑和沮喪,並被視為“必不可少的惡魔”。如果您使它易於使用,以使新手程式設計師可以開始使用它,那麼就不必再痛苦了。全面-沒有任何其他安全框架具有Apache Shiro所聲稱的範圍廣度,因此它很可能是滿足您的安全需求的“一站式服務”。靈活-Apache Shiro可以在任何應用程式環境中工作。雖然它可以在Web,EJB和IoC環境中執行,但不需要它們。 Shiro也不要求任何規範,甚至沒有很多依賴性。具有Web功能-Apache Shiro具有出色的Web應用程式支援,可讓您基於應用程式URL和Web協議(例如REST)建立靈活的安全策略,同時還提供了一組JSP庫來控制頁面輸出。可插拔-Shiro簡潔的API和設計模式可輕鬆與許多其他框架和應用程式整合。您會看到Shiro與Spring,Grails,Wicket,Tapestry,Mule,Apache Camel,Vaadin等框架無縫整合。受支援-Apache Shiro是Apache Software Foundation的一部分,該組織被證明以其社群的最大利益行事。專案開發和使用者群體友好的公民隨時可以提供幫助。如果需要,像Katasoft這樣的商業公司也可以提供專業的支援和服務。核心概念:Subject,SecurityManager 和 RealmsShiro的體系結構具有三個主要概念-主題(Subject),安全管理器(SecurityManager)和領域(Realms)。
概念
Subject在保護應用程式安全時,可能要問自己最相關的問題是:“當前使用者是誰?”或“是否允許當前使用者執行X”?
在編寫程式碼或設計使用者介面時,我們通常會問自己以下問題:應用程式通常是基於使用者案例構建的,並且您希望基於每個使用者來表示(和保護)功能。
因此,我們考慮應用程式安全性的最自然方法是基於當前使用者。
Shiro的API從根本上代表了這種思維方式。
“主題”一詞是一個安全術語,基本上表示“當前正在執行的使用者”。它只是不被稱為“使用者”,因為“使用者”一詞通常與人類相關聯。
在安全領域中,“主題”一詞可以表示一個人,但也可以指第三方程序,守護程式帳戶或任何類似內容。它僅表示“當前正在與軟體互動的事物”。
不過,對於大多數意圖和目的,您都可以將其視為Shiro的“使用者”概念。
您可以在程式碼中的任何位置輕鬆獲取Shiro主題,如下面的清單1所示。
List1import org.apache.shiro.subject.Subject;import org.apache.shiro.SecurityUtils;...Subject currentUser = SecurityUtils.getSubject();
獲取主題後,您可以立即訪問當前使用者想要使用Shiro進行的所有操作的90%,例如登入,登出,訪問其會話,執行授權檢查等等-但稍後會介紹更多 。
這裡的關鍵是Shiro的API在很大程度上是直觀的,因為它反映了開發人員在“每使用者”安全控制中進行思考的自然趨勢。
在程式碼中的任何地方訪問主題也很容易,從而可以在需要的地方進行安全操作。
安全管理器主題的“幕後”對應物件是SecurityManager。
主題代表當前使用者的安全操作,而SecurityManager管理所有使用者的安全操作。它是Shiro體系結構的核心,是一種“傘”物件,它引用了許多內部巢狀的安全元件,這些安全元件構成了一個物件圖。但是,一旦配置了SecurityManager及其內部物件圖,通常就不理會它,應用程式開發人員幾乎將所有時間都花在Subject API上。
那麼如何設定SecurityManager?
好吧,這取決於您的應用程式環境。
例如,Web應用程式通常將在web.xml中指定Shiro Servlet過濾器,這將設定SecurityManager例項。如果您執行的是獨立應用程式,則需要以其他方式進行配置。但是有許多配置選項。
每個應用程式幾乎總是隻有一個SecurityManager例項。
它本質上是一個應用程式單例(儘管不必是靜態單例)。像Shiro中的幾乎所有內容一樣,預設的SecurityManager實現是POJO,並且可以使用任何與POJO相容的配置機制-常規Java程式碼,Spring XML,YAML,.properties和.ini檔案等進行配置。基本上,任何能夠例項化類的東西並且可以使用與JavaBeans相容的呼叫方法。
為此,Shiro透過基於文字的INI配置提供了預設的“共母”解決方案。
INI易於閱讀,易於使用,並且幾乎不需要依賴項。您還將看到,透過簡單地瞭解物件圖導航,可以有效地使用INI來配置簡單的物件圖,例如SecurityManager。
請注意,Shiro還支援Spring XML配置和其他替代方案,但我們將在此處介紹INI。
下面的清單2中的示例顯示了基於INI配置Shiro的最簡單示例。
List2 使用 INI 配置[main]cm = org.apache.shiro.authc.credential.HashedCredentialsMatchercm.hashAlgorithm = SHA-512cm.hashIterations = 1024# Base64 encoding (less text):cm.storedCredentialsHexEncoded = falseiniRealm.credentialsMatcher = $cm[users]jdoe = TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJpcyByZWFzb2asmith = IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbXNoZWQsIG5vdCB
在清單2中,我們看到了用於配置SecurityManager例項的INI配置示例。
INI分為兩個部分:[main]和[users]。
[main]部分是配置SecurityManager物件和/或SecurityManager使用的任何物件(如領域)的地方。在此示例中,我們看到兩個物件被配置:
cm物件,它是Shiro的HashedCredentialsMatcher類的例項。如您所見,cm例項的各種屬性是透過“巢狀點”語法配置的,該語法由清單3所示的IniSecurityManagerFactory用來表示物件圖導航和屬性設定。
iniRealm物件,是SecurityManager用來表示以INI格式定義的使用者帳戶的元件。
在[使用者]部分中,您可以指定使用者帳戶的靜態列表-適用於簡單的應用程式或測試時。
出於本簡介的目的,理解每一部分的複雜性並不重要,而是要了解INI配置是配置Shiro的一種簡單方法。
有關INI配置的更多詳細資訊,請參閱Shiro的文件。
List3 載入配置檔案import org.apache.shiro.SecurityUtils;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.util.Factory;//1. Load the INI configurationFactory<SecurityManager> factory =new IniSecurityManagerFactory("classpath:shiro.ini");//2. Create the SecurityManagerSecurityManager securityManager = factory.getInstance();//3. Make it accessibleSecurityUtils.setSecurityManager(securityManager);
在清單3中,在這個簡單的示例中,我們看到了一個三步過程:
載入將配置SecurityManager及其組成元件的INI配置。根據配置(使用代表工廠方法設計模式的Shiro的工廠概念)建立SecurityManager例項。使SecurityManager單例可被應用程式訪問。在這個簡單的示例中,我們將其設定為VM靜態單例,但這通常不是必需的-您的應用程式配置機制可以確定是否需要使用靜態記憶體。
Realms(領域)Shiro中的第三個也是最後一個核心概念是領域。
領域充當Shiro與應用程式的安全資料之間的“橋樑”或“聯結器”。
也就是說,當需要真正與安全性相關的資料(例如使用者帳戶)進行互動以執行身份驗證(登入)和授權(訪問控制)時,Shiro會從為一個應用程式配置的一個或多個Realms中查詢其中的許多內容。
從這個意義上說,領域本質上是特定於安全性的DAO:它封裝了資料來源的連線詳細資訊,並根據需要使關聯資料可用於Shiro。在配置Shiro時,您必須至少指定一個領域用於身份驗證和/或授權。可以配置多個Realm,但至少需要一個。
Shiro提供了開箱即用的領域,可以連線到許多安全資料來源(又名目錄),例如LDAP,關係資料庫(JDBC),文字配置源(例如INI和屬性檔案)等等。
如果預設的Realms不能滿足您的需求,那麼您可以插入自己的Realm實現以表示自定義資料來源。
下面的清單4是配置Shiro(透過INI)以將LDAP目錄用作應用程式的領域之一的示例。
清單4.示例領域配置[main]ldapRealm = org.apache.shiro.realm.ldap.JndiLdapRealmldapRealm.userDnTemplate = uid={0},ou=users,dc=mycompany,dc=comldapRealm.contextFactory.url = ldap://ldapHost:389ldapRealm.contextFactory.authenticationMechanism = DIGEST-MD5
現在,我們已經瞭解瞭如何設定基本的Shiro環境,讓我們討論您作為開發人員如何使用該框架。
詳細架構下圖顯示了Shiro的核心架構概念,並簡要概述了每個架構:
詳細架構
下面我們對除了核心元件的部分做一下簡單的介紹:
Authentication(身份驗證)身份驗證是驗證使用者身份的過程。
也就是說,當用戶透過應用程式進行身份驗證時,他們在證明自己實際上就是他們所說的身份。有時也稱為“登入”。
這通常是一個三步過程。
收集使用者的識別資訊(稱為主體)和支援身份證明的憑據(稱為憑據)。將主體和憑據提交到系統。如果提交的憑據與系統對該使用者身份(本金)的期望匹配,則認為該使用者已透過身份驗證。如果不匹配,則認為該使用者未透過身份驗證。每個人都熟悉的此過程的一個常見示例是使用者名稱/密碼組合。當大多數使用者登入軟體應用程式時,通常會提供其使用者名稱(主體)和支援密碼(憑據)。如果儲存在系統中的密碼(或密碼錶示形式)與使用者指定的密碼匹配,則認為它們已透過身份驗證。
Shiro以簡單直觀的方式支援相同的工作流程。
正如我們所說,Shiro具有以主題為中心的API-在執行時,您與Shiro所做的幾乎所有事情都是透過與當前正在執行的Subject進行互動來實現的。
因此,要登入主題,您只需呼叫其登入方法,並傳遞一個AuthenticationToken例項,該例項代表所提交的主體和憑據(在本例中為使用者名稱和密碼)。
此示例在下面的清單5中顯示。
列表5 主題登入//1. Acquire submitted principals and credentials:AuthenticationToken token =new UsernamePasswordToken(username, password);//2. Get the current Subject:Subject currentUser = SecurityUtils.getSubject();//3. Login:currentUser.login(token);
如您所見,Shiro的API可以輕鬆反映常見的工作流程。
您會繼續將這種簡單性視為主題操作的所有操作的主題。
當呼叫登入方法時,SecurityManager將接收AuthenticationToken並將其分發給一個或多個配置的領域,以允許每個領域根據需要執行身份驗證檢查。
每個領域都可以根據需要對提交的AuthenticationToken做出反應。
但是,如果登入嘗試失敗會怎樣?
如果使用者指定了錯誤的密碼怎麼辦?
您可以透過對Shiro的執行時AuthenticationException做出反應來處理故障,如清單6所示。
列表6-處理失敗的場景//3. Login:try { currentUser.login(token);} catch (IncorrectCredentialsException ice) { …} catch (LockedAccountException lae) { …}…catch (AuthenticationException ae) {…}
您可以選擇捕獲AuthenticationException子類之一併作出具體反應,或者一般性地處理任何AuthenticationException(例如,向用戶顯示通用的“使用者名稱或密碼錯誤”訊息)。
選擇取決於您,具體取決於您的應用程式需求。
主題成功登入後,它們被認為已透過身份驗證,通常您允許他們使用您的應用程式。
但是,僅僅因為使用者證明了自己的身份並不意味著他們可以在應用程式中做任何想做的事情。
這就引出了下一個問題:“如何控制允許使用者執行或不執行的操作?” 確定允許使用者執行的操作稱為授權。
接下來,我們將介紹Shiro如何啟用授權。
Authorization(授權)授權本質上是訪問控制-控制使用者可以在應用程式中訪問的內容(例如資源,網頁等)。
大多數使用者透過使用角色和許可權等概念來執行訪問控制。
也就是說,通常根據分配給他們的角色和/或許可權,允許使用者執行某項操作或不執行某項操作。
然後,您的應用程式可以根據對這些角色和許可權的檢查來控制公開哪些功能。
如您所料,主題API使您可以非常輕鬆地執行角色和許可權檢查。
例如,清單7中的程式碼片段顯示瞭如何檢查Subject是否被分配了特定角色。
清單7-角色檢查if ( subject.hasRole("administrator") ) { //show the ‘Create User’ button} else { //grey-out the button?}
如您所見,您的應用程式可以基於訪問控制檢查來啟用或禁用功能。
許可權檢查是執行授權的另一種方法。
為此,Shiro支援其許可權概念。
透過使許可權反映您的應用程式的原始功能,您只需更改許可權檢查何時更改應用程式的功能。反過來,您可以在執行時根據需要向角色或使用者分配許可權。
作為一個示例,如下面的清單8所示,我們可以重寫之前的角色檢查,而使用許可權檢查。
清單8-許可權檢測if (subject.isPermitted("user:create") ) { //show the ‘Create User’ button} else { //grey-out the button?}
這樣,分配了 user:create 許可權的任何角色或使用者都可以單擊“Create User”按鈕,並且這些角色和分配甚至可以在執行時更改,從而為您提供了非常靈活的安全模型。
“usercreate”字串是遵循某些解析約定的許可權字串的示例。
Shiro的WildcardPermission支援此約定。
清單9-例項級別許可權校驗if ( subject.isPermitted(“user:delete:jsmith”) ) { //delete the ‘jsmith’ user} else { //don’t delete ‘jsmith’}
此示例表明,如果需要,您可以控制甚至訪問非常細緻的例項級別。
如果願意,您甚至可以發明自己的許可權語法。
有關更多資訊,請參見 Shiro許可權文件。
最後,與身份驗證一樣,上述呼叫最終也進入了SecurityManager,後者將諮詢一個或多個Realms來做出訪問控制決策。 這使領域可以根據需要響應身份驗證和授權操作。
這就是Shiro授權功能的簡要概述。
儘管大多數安全框架都停止了身份驗證和授權,但Shiro提供了更多功能。
會話管理Apache Shiro在安全框架領域提供了一些獨特的功能:可在任何應用程式和任何體系結構層中使用的一致的Session API。
也就是說,Shiro為任何應用程式啟用了會話程式設計範例-從小型守護程式獨立應用程式到最大的群集Web應用程式。
這意味著希望使用會話的應用程式開發人員不再需要,則不再需要使用Servlet或EJB容器。或者,如果使用這些容器,則開發人員現在可以選擇在任何層中使用統一且一致的會話API,而不是使用servlet或EJB特定的機制。
但是Shiro會話的最重要好處之一就是它們與容器無關。
這具有微妙但極其強大的含義。
例如,讓我們考慮會話叢集。有多少種特定於容器的方式可以將會話群集在一起以實現容錯和故障轉移?
Tomcat與Jetty的功能不同,而Jetty與Websphere的功能不同。但是,透過Shiro會話,您可以獲得獨立於容器的叢集解決方案。
Shiro的體系結構允許可插入的Session資料儲存,例如企業快取,關係資料庫,NoSQL系統等等。
這意味著您只需配置一次會話叢集,無論部署環境如何(Tomcat,Jetty,JEE Server或獨立應用程式),它都將以相同的方式工作。
無需根據部署應用程式的方式重新配置應用程式。
Shiro會話的另一個好處是,如果需要,會話資料可以跨客戶端技術共享。
例如,如果需要,Swing桌面客戶端可以參加相同的Web應用程式會話-如果終端使用者同時使用這兩個客戶端,則很有用。
那麼,您如何在任何環境中訪問主題的會話?
如下面的示例所示,有兩種Subject方法。
Listing 10. Subject’s SessionSession session = subject.getSession();Session session = subject.getSession(boolean create);
如您所見,這些方法在概念上與HttpServletRequest API相同。
第一種方法將返回主題的現有會話,或者如果沒有,則建立一個新的會話並返回。
第二種方法接受一個布林引數,該引數確定是否將建立一個新的會話(如果尚不存在)。
獲取主題的會話後,就可以將其幾乎與HttpSession一樣使用。
Shiro團隊認為HttpSession API最適合Java開發人員,因此我們保留了大部分感覺。
當然,最大的區別是您可以在任何應用程式中使用Shiro Sessions,而不僅僅是Web應用程式。
清單11顯示了這種熟悉程度。
Listing 11. Session methodsSession session = subject.getSession();session.getAttribute("key", someValue);Date start = session.getStartTimestamp();Date timestamp = session.getLastAccessTime();session.setTimeout(millis);
密碼學
密碼術是隱藏或混淆資料的過程,因此窺探眼睛無法理解它。
Shiro的加密目標是簡化JDK的加密支援並使之可用。
需要特別注意的是,密碼通常不是特定於主題的,因此Shiro API的其中一個領域不是特定於主題的。
即使未使用“主題”,您也可以在任何地方使用Shiro的加密支援。
Shiro真正側重於其加密支援的兩個領域是加密雜湊(又名訊息摘要)和加密密碼領域。
讓我們更詳細地看看這兩個。
雜湊如果您使用了JDK的MessageDigest類,您很快就會意識到使用它有點麻煩。它具有笨拙的基於靜態方法的基於工廠的API,而不是面向物件的API,因此您不得不捕獲可能永遠不需要捕獲的已檢查異常。如果您需要十六進位制編碼或Base64編碼的訊息摘要輸出,則由您自己決定-兩者均不提供標準的JDK支援。
Shiro透過乾淨直觀的雜湊API解決了這些問題。
例如,讓我們考慮MD5雜湊檔案並確定該雜湊的十六進位制值的相對常見的情況。稱為“校驗和”,通常在提供檔案下載時使用-使用者可以對下載的檔案執行自己的MD5雜湊,並斷言其校驗和與下載站點上的校驗和匹配。如果它們匹配,則使用者可以充分假設檔案在傳輸過程中未被篡改。
在沒有Shiro的情況下,您可以嘗試以下操作:
將檔案轉換為位元組陣列。 JDK中沒有任何東西可以幫助您解決此問題,因此您需要建立一個輔助方法,該方法可以開啟FileInputStream,使用位元組緩衝區並丟擲適當的IOException等。使用MessageDigest類對位元組陣列進行雜湊處理,以處理適當的異常,如下面的清單12所示。將雜湊位元組陣列編碼為十六進位制字元。 JDK中也沒有任何東西可以提供幫助,因此您需要建立另一個幫助器方法,並可能在實現中使用按位運算和移位。Listing 12. JDK’s MessageDigesttry { MessageDigest md = MessageDigest.getInstance("MD5"); md.digest(bytes); byte[] hashed = md.digest();} catch (NoSuchAlgorithmException e) { e.printStackTrace();}
對於如此簡單且相對常見的事物而言,這是一項巨大的工作。
現在,說明如何使用Shiro進行完全相同的操作。
String hex = new Md5Hash(myFile).toHex();
使用Shiro簡化所有工作時,瞭解正在發生的事情非常簡單和容易。
SHA-512雜湊和密碼的Base64編碼也很容易。
String encodedPassword = new Sha512Hash(password, salt, count).toBase64();
您會看到Shiro在很大程度上簡化了雜湊和編碼,從而在此過程中節省了一些理智。
密碼密碼是可以使用金鑰可逆地轉換資料的密碼演算法。我們使用它們來保護資料安全,尤其是在傳輸或儲存資料時,尤其是在資料容易被撬開的時候。
如果您曾經使用過JDK密碼API,尤其是javax.crypto.Cipher類,那麼您就會知道,馴服它可能是一件極其複雜的事情。對於初學者來說,每種可能的Cipher配置始終由javax.crypto.Cipher的例項表示。
需要做公鑰/私鑰加密嗎?
您使用密碼。是否需要使用分組密碼進行流操作?您使用密碼。是否需要建立AES 256位密碼來保護資料?您使用密碼。你明白了。
以及如何建立所需的Cipher例項?
您建立了一個複雜的,不直觀的,用令牌分隔的密碼選項字串,稱為“轉換字串”,並將該字串傳遞給Cipher.getInstance靜態工廠方法。使用這種密碼選項字串方法,沒有型別安全性來確保您使用有效的選項。這也隱含地意味著沒有JavaDoc可以幫助您瞭解相關選項。而且,即使您知道配置正確,也需要處理經過檢查的異常,以防您的字串格式錯誤。如您所見,使用JDK Ciphers是一項繁瑣的任務。這些技術很久以前曾經是Java API的標準,但是時代已經改變,我們希望有一種更簡單的方法。
Shiro試圖透過引入其CipherService API簡化整個密碼演算法的概念。
大多數開發人員在保護資料時都希望使用CipherService:一種簡單,無狀態,執行緒安全的API,可以在一個方法呼叫中完整地加密或解密資料。您所需要做的就是提供金鑰,然後可以根據需要加密或解密。
例如,可以使用256位AES加密,如下面的清單13所示。
Listing 13. Apache Shiro’s Encryption APIAesCipherService cipherService = new AesCipherService();cipherService.setKeySize(256);//create a test key:byte[] testKey = cipherService.generateNewKey();//encrypt a file’s bytes:byte[] encrypted = cipherService.encrypt(fileBytes, testKey);
與JDK的Cipher API相比,Shiro示例更簡單:
您可以直接例項化CipherService-沒有奇怪或令人困惑的工廠方法。密碼配置選項表示為與JavaBeans相容的getter和setter-沒有奇怪且難以理解的“轉換字串”。加密和解密在單個方法呼叫中執行。沒有強制檢查的異常。 如果需要,請捕獲Shiro的CryptoException。Shiro的CipherService API還有其他好處,例如既支援基於位元組陣列的加密/解密(稱為“塊”操作),又支援基於流的加密/解密(例如,加密音訊或影片)。
Java密碼術不必太痛苦。
Shiro的密碼學支援旨在簡化您保護資料安全的工作。
web 支援最後但並非最不重要的一點,我們將簡要介紹Shiro的 web 支援。
Shiro隨附了強大的Web支援模組,以幫助保護Web應用程式。
為Web應用程式設定Shiro很簡單。 唯一需要做的就是在web.xml中定義一個Shiro Servlet過濾器。
清單14顯示了此程式碼。
配置完成後,Shiro篩選器將篩選每個請求,並確保在請求期間可訪問特定於請求的主題。
並且因為它過濾了每個請求,所以您可以執行特定於安全性的邏輯,以確保僅允許滿足特定條件的請求透過。
URL特定的過濾器鏈Shiro透過其創新的URL過濾器連結功能支援特定於安全性的過濾器規則。
它允許您為任何匹配的URL模式指定臨時過濾器鏈。
這意味著您在使用Shiro的過濾機制執行安全規則(或規則組合)方面具有很大的靈活性-比僅在web.xml中定義過濾器要強得多。
清單15顯示了Shiro INI中的配置程式碼段。
Listing 15. Path-specific Filter Chains[urls]/assets/** = anon/user/signup = anon/user/** = user/rpc/rest/** = perms[rpc:invoke], authc/** = authc
如您所見,Web應用程式有一個[urls] INI部分。對於每一行,等號左側的值代表上下文相關的Web應用程式路徑。右側的值定義了一個Filter鏈-要對給定路徑執行的Servlet過濾器的列表,以逗號分隔。
每個過濾器都是一個普通的Servlet過濾器,但是您在上面看到的過濾器名稱(匿名,使用者,許可權,身份驗證)是Shiro提供的與安全相關的特殊過濾器。
您可以混合使用這些安全過濾器,以建立非常自定義的安全體驗。您還可以指定可能具有的任何其他現有Servlet過濾器。
與使用web.xml(定義一個過濾器塊,然後定義一個分離的過濾器模式塊)相比,這要好多少?
使用Shiro的方法,可以更輕鬆地準確檢視針對給定匹配路徑執行的過濾器鏈。
如果需要,可以在web.xml中僅定義Shiro過濾器,並在shiro.ini中定義所有其他過濾器和過濾器鏈,以使過濾器鏈定義機制比web.xml更加簡潔明瞭。
即使您沒有使用Shiro的任何安全功能,僅此一項小小的便利都可以使Shiro值得使用。
JSP標籤庫Shiro還提供了一個JSP標記庫,透過該庫,您可以根據當前Subject的狀態來控制JSP頁面的輸出。
一個有用的常見示例是在使用者登入後顯示 Hello <username> 文字。
但是,如果它們是匿名的,則可能需要顯示其他內容,例如 Hello! Register Today! 代替。
清單16顯示瞭如何使用Shiro的JSP標籤支援這一點。
Shiro還支援許多其他特定於Web的功能,例如簡單的“ Remember Me”服務,REST和BASIC身份驗證,當然,如果要使用Shiro的本機企業會話,則當然還支援透明的HttpSession支援。
web 會話管理最後,指出Shiro對網路環境中的會話的支援很有趣。
預設Http會話對於Web應用程式,Shiro將其會話基礎結構預設為使用我們都習慣的現有Servlet容器會話。
也就是說,當您呼叫方法subject.getSession()和subject.getSession(boolean)時,Shiro將返回由Servlet容器的HttpSession例項支援的Session例項。
這種方法的優點在於,呼叫subject.getSession()的業務層程式碼與Shiro Session例項進行互動-它不具備與基於Web的HttpSession物件一起工作的“知識”。
在跨架構層保持清晰隔離時,這是一件非常好的事情。
Web層中Shiro的本機會話如果您由於需要Shiro的企業會話功能(例如與容器無關的叢集)而在Web應用程式中啟用了Shiro的本機會話管理,那麼您當然希望HttpServletRequest.getSession()和HttpSession API與“本機”會話一起使用,並且而不是Servlet容器會話。
如果您必須重構任何使用HttpServletRequest和HttpSession API的程式碼來替代使用Shiro的Session API,那將非常令人沮喪。
Shiro當然不會期望您這樣做。
相反,Shiro完全實現了Servlet規範的Session部分,以支援Web應用程式中的本機會話。
這意味著無論何時呼叫相應的HttpServletRequest或HttpSession方法呼叫,Shiro都會將這些呼叫委派給其內部的本地Session API。
最終結果是,即使您使用的是Shiro的“本地”企業會話管理,也不必更改Web程式碼-確實是非常方便(且必不可少)的功能。
附加功能Apache Shiro框架中還有其他對保護Java應用程式有用的功能,例如:
1, 執行緒和併發支援,用於跨執行緒維護主題(Executor和ExecutorService支援)
可呼叫和可執行支援將邏輯作為特定主題執行“執行方式”支援,用於假設另一個主題的身份(例如在管理應用程式中很有用)測試工具支援,使在單元測試和整合測試中對Shiro安全程式碼進行全面測試變得非常容易框架侷限性就像我們希望的那樣,Apache Shiro並不是“銀彈”-它不會輕鬆解決所有安全問題。
Shiro無法解決的某些事情可能值得了解:
虛擬機器級別的問題Apache Shiro當前不處理虛擬機器級別的安全性,例如基於訪問控制策略阻止某些類載入到類載入器中的能力。
但是,Shiro可以與現有的JVM安全操作整合是不可想象的-只是沒有人為該專案做出過這樣的貢獻。
多階段身份驗證Shiro當前不本地支援“多階段”身份驗證,在這種情況下,使用者可能透過一種機制登入,只是被要求然後使用另一種機制再次登入。
這已在基於Shiro的應用程式中完成,但是該應用程式會預先收集所有必需的資訊,然後與Shiro進行互動。很有可能在將來的Shiro版本中支援此功能。
領域寫入操作目前,所有Realm實施都支援“讀取”操作,以獲取身份驗證和授權資料以執行登入和訪問控制。
不支援“寫入”操作,例如建立使用者帳戶,組合角色,或將使用者與角色組和許可權相關聯。這是因為支援這些操作的資料模型在不同的應用程式中差異很大,並且很難在所有Shiro使用者上強制執行“寫入” API。
小結Apache Shiro 是功能齊全,健壯且通用的Java安全框架,可用於保護應用程式安全。
透過簡化應用程式安全性的四個領域,即身份驗證,授權,會話管理和密碼學,可以更輕鬆地在實際應用程式中理解和實現應用程式安全性。
我是老馬,期待與你的下次相遇。