天天看點

shiro實戰系列(四)之配置

                                   Shiro之配置

Shiro 被設計成能夠在任何環境下工作,從最簡單的指令行應用程式到最大的的企業群集應用。由于環境的多樣性,使得許多配置機制适用于它的配置。

一、 許多配置選項

Shiro的SecurityManager實作及所支援的元件都是相容JavaBean的。這使得Shiro幾乎能使用任何配置格式,如regular Java,XML(Spring, JBoss, Guice,等等),YAML,JSON,Groovy Builder markup,以及更多的配置。

二、 可程式設計配置

建立一個 SecurityManger 并把它提供給應用程式的絕對的最簡單的方法是建立一個 org.apache.shiro.mgt.DefaultSecurityManager 并把它鍊到代碼中。

shiro實戰系列(四)之配置

三、 安全管理器對象圖

Shiro 的 SecurityManager 實作實質上是一個特定安全的嵌套元件中的子產品化對象圖。因為它們也是相容 JavaBean 的,你可以調用任何嵌套元件的 getter 和 setter 方法來配置 SecurityManager 以及它的内部對象圖。

例如,如果你想配置 SecurityManager 執行個體來使用自定義的 SessionDAO 來定制 Session Management,你可以通過嵌 套的 SessionManager 的 setSessionDAO 方法直接設定 SessionDAO:

shiro實戰系列(四)之配置

通過使用直接方法調用,你可以配置 SecurityManager 的對象圖的任何部分。

但是,程式化定制過于簡單,它并不能代表大多數現實世界的應用程式的理想配置。以下是程式化定制可能不适合 你的幾點原因:  它需要你了解和執行個體化一個直接實作。這将會更好,如果你不需要了解具體的實作和在哪裡可以找到它們。  由于 Java 的類型安全性,你需要轉換通過 get*方法擷取的對象來得到它們具體的實作。如此多的轉換是醜陋 的,冗長的,并使你和實作類緊密連接配接起來。  SecurityUtils.setSecurityManager 方法調用在一個 VM 靜态單例中執行個體化 SecurityManager 執行個體,VM 靜态單例 在給許多應用程式帶來好處的同時,也會引發一些問題,如果多個啟用 Shiro 的應用程式在同一個 JVM 中運作。如果該執行個體是一個應用程式單例,而不是一個靜态記憶體引用就再好不過了。  每當你想改變 Shiro 配置時,它需要你重新編譯你的應用程式。   然而,即使有這麼多警告,直接的程式設計操作方法在記憶體受限的環境中仍然是有價值的,如智能手機應用。若你的應用程式不在一個記憶體受限的環境下運作,你會發現基于文本的配置要更容易使用和閱讀。

四、 ini配置

大多數應用程式反而從基于文本的配置受益,能夠獨立地修改源代碼,甚至讓那些不熟悉 Shiro 的 API 的人能夠更 容易了解。

為了確定一個基于文本的通用标準配置機制能夠在所有環境下以最小的第三方依賴工作,Shiro 支援 INI 格式來建構 SecurityManager 對象圖及其支援的元件。INI 易于閱讀,易于配置,且設定簡單,适合大多數應用程式。

(1)    來自ini執行個體的安全管理器

如果你需要,INI 配置也可以通過 org.apache.shiro.config.Ini 類使用程式設計方式建立。Ini 類的功能與 JDK java.util.Properties 類相似,但通過 section 名稱,它同時還支援分割。

shiro實戰系列(四)之配置

  現在,我們知道如何從 INI 配置建構出一個 SecurityManager 了,我們看看到底是如何定義一個 Shiro INI 配置的。

(2)    INI Sections

INI 基本上是一個文本配置,包含了由唯一命名的 section 組織的鍵/值對。鍵隻是每個 section 唯一,而不是在整個 配置中(與 JDK 屬性不同)。不過每個 section 都可以被看作單一的屬性定義。   注釋行能夠以散列字元(# - 也就是"hash","pound"或"number"符号)或分号(";")開始。

以下就是shiro能夠了解section的例子:

shiro實戰系列(四)之配置

[main]

[main] section 是你配置應用程式的 SecurityManager 執行個體及任何它的依賴元件(如 Realms)的地方。   配置對象執行個體,如 SecurityManager 或任何它的依賴元件,通過使用 INI 聽起來是一件困難的事情,我們僅能使用名 稱/值對。但通過一點點約定和對對象圖的了解,你将會發現你可以做很多事情。Shiro 使用這些條件來簡單卻相當 簡潔的配置機制。   我們往往喜歡把這種方法稱為“窮人的”依賴注入,雖然沒有完全成熟的 Spring/Guice/JBoss XML 檔案強大,但你将 會發現它能夠完成許多事情卻沒有太多的複雜性。當然那些其他的配置機制也同樣可用,但它們不是使用 Shiro 所 必需的。 

為了激起你的欲望,這裡有一個有效的[main]配置的例子。我們将在下面讨論它的細節,但你可能會發現,僅憑直 覺就能明白很多事情是怎麼回事:

shiro實戰系列(四)之配置

這一行執行個體化了 com.company.shiro.realm.MyRealm 類型的新的對象執行個體,并使該對象使用 myRealm 名稱,以供進 一步的引用和配置。   如果該執行個體化的對象實作了 org.apache.shiro.util.Nameable 接口,則 Nameable.setName 方法将會在擁有該名字(在 本例中是 myRealm)的對象上調用。  

注意:

每個對象的執行個體化以及每個值得配置設定都是按照它們在[main] section 中出現的順序來執行的。這些配置行最終轉化成 一個 JavaBean 的 getter/setter 方法調用,是以,這些方法以同樣的順序被調用! 當你編寫你的配置時,請記住這點。

[users]

[users] section 允許你定義一組靜态的使用者帳戶。這在大部分擁有少數使用者帳戶或使用者帳戶不需要在運作時被動态地 建立的環境下是很有用的。以下是一個例子:

shiro實戰系列(四)之配置

a.Automatic IniRealm :

僅定義非空的[users]或[roles] section 将會自動地觸發 org.apache.shiro.realm.text.IniRealm 執行個體的建立,并使它在 [main] section 中可用且名為 iniRealm。你可以像上面所描述的其他對象一樣來配置它。

b.Line Format

在[users] section 中的每行都必須保證是下面的格式:

 username = password, roleName1, roleName2, …, roleNameN   

在等号左邊的值是使用者名。

在等号右邊的第一個值是使用者的密碼,密碼是必須的。 

任何在密碼後用逗号分隔的值都是配置設定給該使用者的角色名。角色名是可選的。

c.Encrypting Passwords

如果你不想[users] section 中密碼是純文字的,你可以使用你喜愛的雜湊演算法(MD5,Sha1,Sha256,等等)來進行加密,并使用生産的字元串作為密碼值。預設情況下,密碼字元串是 16 進制編碼,但可以使用 Base64 編碼代替 16 進制編碼來配置(見下面)。

一旦你指定了文本密碼散列值,你得告訴 Shiro 這些都是加密的。你可以通過配置在[main] section 中隐式地建立 iniRealm 來使用合适的 CredentialsMatcher 實作來對應到你所指定的雜湊演算法:

你可以像任何其他對象一樣在 CredentialsMatcher 上配置任何屬性,以反映你哈希政策,例如,指定 salting 是否被使用或需要執行多少次哈希疊代。請參見 org.apache.shiro.authc.credential.HashedCredentialsMatcher 的 JavaDoc 來更好的了解哈希政策,如果它們對你可能有用的話。  

例如,如果你的使用者密碼字元串是 Base64 編碼而不是預設的 16 進制,你可以指定說明:

[roles]

[roles] section 允許你把定義在[users] section 中的角色與權限關聯起來。另外,這在大部分擁有少數使用者帳戶或使用者 帳戶不需要在運作時被動态地建立的環境下是很有用的。以下是一個例子:

shiro實戰系列(四)之配置

Line Format

在[roles] section 中每個配置行必須定義一個映射以下格式的角色到權限的鍵/值:   rolename = permissionDefinition1, permissionDefinition2, … , permissionDefinitionN   permissionDefinition 是一個任意的字元串,但大多數人将會使用符合 org.apache.shiro.authz.permission.WildcardPermission 格式的字元串,為了易用性和靈活性。請參見 Permissions 文檔 擷取更多關于 Permissions 及你如何從它們受益的資訊。

Internal commas                

請注意,如果一個獨立的 permissionDefinition 需要被内部逗号分隔(例如,printer:5thFloor:print,info),你需要使用者雙引号環繞該定義,以避免錯誤解析: "printer:5thFloor:print,info" 

Roles without Permissions 

如果你有不需要權限關聯的角色,你不需要在[roles] section 中間把他們列出來,如果你不想的話。隻需定義在[user] section 中定義角色名就足以建立尚不存在的角色。