更新時間:2022-11-21 08:58:00 來源:動力節點 瀏覽1507次
Shiro 旨在在任何環境中工作,從簡單的命令行應用程序到最大的企業集群應用程序。由于環境的這種多樣性,因此有許多適合配置的配置機制。
創建 SecurityManager 并使其對應用程序可用的絕對最簡單的方法是創建一個org.apache.shiro.mgt.DefaultSecurityManager并在代碼中連接它。例如:
Realm realm = //instantiate or acquire a Realm instance. We'll discuss Realms later.
SecurityManager securityManager = new DefaultSecurityManager(realm);
//Make the SecurityManager instance available to the entire application via static memory:
SecurityUtils.setSecurityManager(securityManager);
Shiro 的SecurityManager實現本質上是嵌套的安全特定組件的模塊化對象圖。因為它們也是 JavaBeans 兼容的,所以您可以調用任何嵌套組件getter和setter方法來配置SecurityManager及其內部對象圖。
例如,如果你想將SecurityManager實例配置為使用自定義SessionDAO來自定義Session Management,你可以SessionDAO直接使用嵌套的 SessionManagersetSessionDAO方法進行設置:
...
DefaultSecurityManager securityManager = new DefaultSecurityManager(realm);
SessionDAO sessionDAO = new CustomSessionDAO();
((DefaultSessionManager)securityManager.getSessionManager()).setSessionDAO(sessionDAO);
...
使用直接方法調用,您可以配置“SecurityManager”對象圖的任何部分。
但是,就像編程定制一樣簡單,它并不代表大多數現實世界應用程序的理想配置。程序化配置可能不適合您的應用程序有以下幾個原因:
它要求您了解并實例化直接實現。如果您不必了解具體的實現以及在哪里可以找到它們,那就更好了。
由于 Java 的類型安全特性,您需要將通過get*方法獲得的對象轉換為它們的特定實現。如此多的轉換是丑陋的、冗長的,并且將您與實現類緊密耦合。
SecurityUtils.setSecurityManager方法調用使實例化的實例SecurityManager成為一個 VM 靜態單例,這對于許多應用程序來說很好,但如果在同一個 JVM 上運行多個啟用 Shiro 的應用程序,則會導致問題。如果實例是應用程序單例而不是靜態內存引用,則可能會更好。
每次您想要更改 Shiro 配置時,它都要求您重新編譯您的應用程序。
然而,即使有這些警告,直接編程操作方法在內存受限的環境中仍然很有價值,例如智能手機應用程序。如果您的應用程序不在內存受限的環境中運行,您會發現基于文本的配置更易于使用和閱讀。
大多數應用程序反而受益于基于文本的配置,這些配置可以獨立于源代碼進行修改,甚至讓那些不熟悉 Shiro 的 API 的人更容易理解。
為確保通用的基于文本的配置機制可以在所有環境中工作且第三方依賴性最小,Shiro 支持INI 格式來構建SecurityManager對象圖及其支持組件。INI 易于閱讀、易于配置、設置簡單,非常適合大多數應用程序。
下面是兩個如何基于 INI 配置構建 SecurityManager 的示例。
我們可以從 INI 資源路徑創建 SecurityManager 實例。資源可以從文件系統、類路徑或分別以 、 或 為前綴的file:URLclasspath:獲取url:。此示例使用 a從類路徑的根目錄中Factory提取文件并返回實例:shiro.iniSecurityManager
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.IniSecurityManagerFactory;
...
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
如果需要,也可以通過org.apache.shiro.config.Ini類以編程方式構建 INI 配置。Ini 類的功能與 JDK 類類似java.util.Properties,但還支持按部分名稱進行分段。
例如:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.Ini;
import org.apache.shiro.config.IniSecurityManagerFactory;
...
Ini ini = new Ini();
//populate the Ini instance as necessary
...
Factory<SecurityManager> factory = new IniSecurityManagerFactory(ini);
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
現在我們知道如何SecurityManager從 INI 配置構建,讓我們來看看如何定義 Shiro INI 配置。
INI 基本上是一個文本配置,由按唯一命名的部分組織的鍵/值對組成。密鑰僅在每個部分是唯一的,而不是在整個配置中(與 JDK Properties不同)。然而,每個部分都可以看作是一個單獨的Properties定義。
注釋行可以以 Octothorpe(# - 又名“井號”、“井號”或“數字”符號)或分號 (';') 開頭
以下是 Shiro 理解的部分示例:
# =======================
# Shiro INI configuration
# =======================
[main]
# Objects and their properties are defined here,
# Such as the securityManager, Realms and anything
# else needed to build the SecurityManager
[users]
# The 'users' section is for simple deployments
# when you only need a small number of statically-defined
# set of User accounts.
[roles]
# The 'roles' section is for simple deployments
# when you only need a small number of statically-defined
# roles.
[urls]
# The 'urls' section is used for url-based security
# in web applications. We'll discuss this section in the
# Web documentation
該[main]部分是您配置應用程序SecurityManager實例及其任何依賴項(例如Realm)的地方。
使用 INI 配置對象實例(如 SecurityManager 或其任何依賴項)聽起來很困難,我們只能使用名稱/值對。但是通過對對象圖的一些約定和理解,您會發現您可以做很多事情。Shiro 使用這些假設來啟用簡單但相當簡潔的配置機制。
我們經常喜歡將這種方法稱為“窮人的”依賴注入,雖然不如成熟的 Spring/Guice/JBoss XML 文件那么強大,但您會發現它可以完成很多工作而沒有太多復雜性。當然那些其他配置機制也可用,但它們不是使用 Shiro 所必需的。
為了激發您的胃口,這里有一個有效[main]配置的示例。我們將在下面詳細介紹它,但您可能會發現僅憑直覺您就已經了解了很多正在發生的事情:
[main]
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
myRealm = com.company.security.shiro.DatabaseRealm
myRealm.connectionTimeout = 30000
myRealm.username = jsmith
myRealm.password = secret
myRealm.credentialsMatcher = $sha256Matcher
securityManager.sessionManager.globalSessionTimeout = 1800000
考慮以下[main]部分片段:
[main]
myRealm = com.company.shiro.realm.MyRealm
...
此行實例化一個新的對象實例,com.company.shiro.realm.MyRealm并使該對象在myRealm名稱下可用,以供進一步參考和配置。
如果實例化的對象實現了org.apache.shiro.util.Nameable接口,則將在名稱為值(在本例中)Nameable.setName的對象上調用該方法。myRealm
原始值
只需使用等號即可分配簡單的原始屬性:
...
myRealm.connectionTimeout = 30000
myRealm.username = jsmith
...
這些配置行轉化為方法調用:
...
myRealm.setConnectionTimeout(30000);
myRealm.setUsername("jsmith");
...
在幕后,Shiro 在設置這些屬性時默認使用 Apache Commons BeanUtils來完成所有繁重的工作。因此,雖然 INI 值是文本,但 BeanUtils 知道如何將字符串值轉換為適當的原始類型,然后調用相應的 JavaBeans setter 方法。
======= 參考值
如果您需要設置的值不是原始值,而是另一個對象怎么辦?那么,您可以使用美元符號 ($) 來引用先前定義的實例。例如:
...
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
...
myRealm.credentialsMatcher = $sha256Matcher
...
這只是定位由名稱sha256Matcher定義的對象,然后使用 BeanUtils 在myRealm實例上設置該對象(通過調用myRealm.setCredentialsMatcher(sha256Matcher)方法)。
嵌套屬性
使用 INI 行等號左側的點分符號,您可以遍歷對象圖以到達您要設置的最終對象/屬性。例如,此配置行:
...
securityManager.sessionManager.globalSessionTimeout = 1800000
...
將(通過 BeanUtils)翻譯成以下邏輯:
securityManager.getSessionManager().setGlobalSessionTimeout(1800000);
圖形遍歷可以根據需要深入:object.property1.property2…?.propertyN.value = blah
字節數組值
因為原始字節數組不能以文本格式本地指定,所以我們必須使用字節數組的文本編碼。這些值可以指定為 Base64 編碼字符串(默認值)或十六進制編碼字符串。默認是 Base64,因為 Base64 編碼需要更少的實際文本來表示值——它有更大的編碼字母表,這意味著你的標記更短(文本配置更好一點)。
# The 'cipherKey' attribute is a byte array. By default, text values # for all byte array properties are expected to be Base64 encoded: securityManager.rememberMeManager.cipherKey = kPH+bIxk5D2deZiIxcaaaA== ...
但是,如果您更喜歡使用十六進制編碼,則必須在字符串標記前加上0x('zero' 'x'):
securityManager.rememberMeManager.cipherKey = 0x3707344A4093822299F31D008
集合屬性
列表、集合和映射可以像任何其他屬性一樣設置 - 直接設置或作為嵌套屬性設置。對于集合和列表,只需指定一組以逗號分隔的值或對象引用。
比如一些SessionListeners:
sessionListener1 = com.company.my.SessionListenerImplementation
...
sessionListener2 = com.company.my.other.SessionListenerImplementation
...
securityManager.sessionManager.sessionListeners = $sessionListener1, $sessionListener2
對于地圖,您指定一個以逗號分隔的鍵值對列表,其中每個鍵值對由冒號“:”分隔
object1 = com.company.some.Class
object2 = com.company.another.Class
...
anObject = some.class.with.a.Map.property
anObject.mapProperty = key1:$object1, key2:$object2
在上面的例子中,引用的對象$object1將在 String key 下的 map 中key1,即map.get("key1")returns object1。您還可以使用其他對象作為鍵:
anObject.map = $objectKey1:$objectValue1, $objectKey2:$objectValue2
...
變量插值
您可以在定義值時使用變量插值。支持的類型是環境變量、系統屬性和常量。
對于常量,使用${const:com.example.YourClass.CONSTANT_NAME},對于環境變量和系統屬性,使用${ENV_VARIABLE_NAME}or ${system.property}。
系統屬性和環境變量按該順序查找。
${const:com.example.YourClass.CONSTANT_NAME:-default_value}默認值以, 或的形式被支持${VARIABLE_NAME:-default_value},例如:
這將被解釋為myRealm.connectionTimeout = 3000好像沒有定義系統屬性或環境變量REALM_CONNECTION_TIMEOUT。
如果沒有找到替換,定義將保持不變。
以上就是關于“Shiro配置文件詳解”的介紹,大家如果想了解更多相關知識,可查看Shiro視頻教程。動力節點在線學習教程,針對沒有任何Java基礎的讀者學習,讓你從入門到精通,主要介紹了一些Java基礎的核心知識,讓同學們更好更方便的學習和了解Java編程。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習