Shiro
ActiveMQ Classic 5.10 及更新版本使用 Apache Shiro 提供完全可自訂的安全性體驗。
ActiveMQ Classic Shiro 外掛程式可以保護 ActiveMQ Classic 代理程式,從驗證傳輸連線到授權主題和佇列的行為,以及介於兩者之間的所有內容。
快速入門
啟用 ShiroPlugin 最快/最簡單的方式是在 broker
plugins
區段中將其定義為 Spring bean,並嵌入 Shiro ini 設定
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="https://activemq.dev.org.tw/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
https://activemq.dev.org.tw/schema/core https://activemq.dev.org.tw/schema/core/activemq-core.xsd">
<broker xmlns="https://activemq.dev.org.tw/schema/core" ... other attributes here ...>
<plugins>
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="iniConfig"><value>
[main]
# Shiro object graph configuration here if desired/necessary
[users]
# users section format:
#
# username = password [, assignedRole1, assignedRole2, ..., assignedRoleN]
#
# for example:
#
# scott = tiger, advisory, users, administrators
#
# Roles and permissions assigned to roles are defined in the [roles] section
# below. By transitive association, any user assigned a role is granted the
# role's permissions.
# ActiveMQ Classic System User
# needed for in-VM/local connections when authentication is enabled:
system = manager, system
# Other users here. You should almost always add the \`advisory\` role for each
# user to make your life easy! See the [roles] comments below for more info.
# jsmith = jsmithsPassword, advisory
# djones = djonesPassword, advisory, ...
# etc.
[roles]
# roles section format:
#
# roleName = wildcardPermission1, wildcardPermission2, ..., wildcardPermissionN
#
# The 'system' role is assigned all permissions (*). Be careful when assigning
# this to actual users other than then system user:
system = *
# Full access rights should generally be given to the ActiveMQ.Advisory.*
# destinations because by default an ActiveMQConnection uses advisory topics to
# get early knowledge of temp destination creation and deletion. For more info:
#
# https://activemq.dev.org.tw/Features/security.md
#
# So we create an 'advisory' role here with a wildcard/catch-all permissions
# for all advisory topics. To make your life easy, ensure you assign this to
# any/all users in the [users] section above, e.g.
#
# jsmith = jsmithsPassword, advisory, ...
advisory = topic:ActiveMQ.Advisory*
</value></property>
</bean>
</plugins>
</broker>
</beans>
此設定假設您有一組簡單/小型的靜態使用者可以存取您的 ActiveMQ Classic 代理程式。我們稍後會介紹如何啟用更進階的使用者儲存庫。
加密密碼
上面的範例使用純文字密碼,設定簡單且易於測試,但並非真正安全。大多數生產部署可能會想要使用加密密碼。例如
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<!-- enabled by default. To disable, uncomment:
<property name="iniConfig"><value>
[main]
# Shiro object graph configuration here
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
iniRealm.credentialsMatcher = $passwordMatcher
[users]
scott = $shiro1$SHA-256$500000$eWpVX2tGX7WCP2J+jMCNqw==$it/NRclMOHrfOvhAEFZ0mxIZRdbcfqIBdwdwdDXW2dM=, advisory
system = $shiro1$SHA-256$500000$eUyGwMGr9GYzB/gg/MoNgw==$WGc0yWFWv8+hLqjzVLgW7Hat2FQTywDXBl5izpqaLSY=, system
[roles]
system = *
advisory = topic:ActiveMQ.Advisory*
</value></property>
</bean>
如您所見,與較簡單/預設設定相比,有兩件事不同
[main]
區段在隱含的iniRealm
上設定了PasswordMatcher
。這表示所有.ini
設定的使用者都應具有適當的雜湊/安全密碼。[users]
行現在在password
位置具有雜湊值,而不是純文字值。
若要取得雜湊密碼文字值,您會想要從 Maven Central 下載 Shiro 的命令列雜湊工具。下載後,您可以使用它來建立安全的密碼雜湊值,您可以安全地複製並貼到 [users]
區段中
$ java -jar shiro-tools-hasher-X.X.X-cli.jar -p
然後它會要求您輸入密碼並確認密碼
Password to hash:
Password to hash (confirm):
當此命令執行時,它會列印出安全加鹽、迭代和雜湊的密碼。例如
$shiro1$SHA-256$500000$eWpVX2tGX7WCP2J+jMCNqw==$it/NRclMOHrfOvhAEFZ0mxIZRdbcfqIBdwdwdDXW2dM=
取得此值並將其作為密碼放在使用者定義行中 (後接任何所需的角色,例如 advisory
角色)。例如
[users]
scott = $shiro1$SHA-256$500000$eWpVX2tGX7WCP2J+jMCNqw==$it/NRclMOHrfOvhAEFZ0mxIZRdbcfqIBdwdwdDXW2dM=, advisory
system = $shiro1$SHA-256$500000$eUyGwMGr9GYzB/gg/MoNgw==$WGc0yWFWv8+hLqjzVLgW7Hat2FQTywDXBl5izpqaLSY=, system
設定
ActiveMQ Classic Shiro 外掛程式可以使用多種方式設定。例如,使用 Java
BrokerService brokerService = new BrokerService();
ShiroPlugin shiroPlugin = new ShiroPlugin();
//configure shiroPlugin via getters/setters here
broker.setPlugins(new BrokerPlugin[]{shiroPlugin});
//continue configuring the brokerService as necessary ...
或者,如果使用傳統的 ActiveMQ Classic xml,則作為 broker
plugins
區段中的 Spring bean。例如
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="https://activemq.dev.org.tw/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
https://activemq.dev.org.tw/schema/core https://activemq.dev.org.tw/schema/core/activemq-core.xsd">
<broker xmlns="https://activemq.dev.org.tw/schema/core" ... other attributes here ...>
<plugins>
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<!-- Config properties via getters/setters as necessary: -->
</bean>
</plugins>
</broker>
</beans>
此頁面上其餘的設定範例將顯示為 bean XML,但請注意,相同的設定可以在 Java 中使用標準 JavaBeans 相容的 getter 和 setter 方法完成。
啟用/停用
您可以完全啟用或停用 ShiroPlugin,而無需將其從設定中移除。這在測試時很方便,或當您想要根據啟動時的設定參數啟用或停用它時很方便。
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<!-- enabled by default. To disable, uncomment:
<property name="enabled" value="false"/> -->
</bean>
一個不錯的技巧是使用 Spring 的 PropertySourcesPlaceholderConfigurer 和預留位置權杖 (在其中一個預留位置屬性檔案中設定 shiro.enabled = true
)
<beans ...>
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
...
</bean>
<broker ...>
<plugins ...>
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="enabled" value="${shiro.enabled}"/>
</bean>
</plugins>
</broker>
</beans>
這可讓您只需在 .properties
檔案中設定屬性,即可啟用或停用 Shiro 外掛程式,而無需變更您的 XML 設定。
Shiro 環境
shiroPlugin
需要 Shiro Environment 才能運作。您必須使用下列方式設定外掛程式
- 您在其他地方建立和設定的
Environment
執行個體 (或 ShiroSecurityManager
執行個體) - 例如,在 Java 程式碼中或 Spring XML 設定中的其他位置,或 - 指定一些 Shiro .ini 設定,以直接字串、Ini 執行個體或 資源路徑 的形式,您的
shiro.ini
檔案位於該路徑。外掛程式將載入 ini 設定並自動建立Environment
。
自訂環境
Shiro Environment
物件包含 Shiro 需要運作的所有內容,並且它也會封裝 Shiro SecurityManager
。如果您想要自行建構和設定 Environment 執行個體
<beans ...>
<broker ...>
<plugins>
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="environment" ref="shiroEnvironment"/>
</bean>
</plugins>
</broker>
<bean id="shiroEnvironment" class="..">
... config here ...
</bean>
<bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>
自訂 SecurityManager
您可以建構 SecurityManager
,而不是設定 Environment
執行個體
<beans ...>
<broker ...>
<plugins>
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="securityManager" ref="shiroSecurityManager"/>
</bean>
</plugins>
</broker>
<bean id="shiroSecurityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">
<property name="realms">
<list>
<bean id="myRealm" class="...">
...
</bean>
... maybe more Realm beans ...
</list>
</property>
</bean>
<bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>
如果指定 SecurityManager
而不是 Environment
屬性,將會自動建立 Environment
,以包裝設定的 SecurityManager
。
shiro.ini 檔案
如果您不想在程式碼或 xml 中建構 SecurityManager
或 Environment
,您可以輕鬆指定 shiro.ini 檔案,並將根據該檔案自動建立 Environment/SecurityManager
<beans ...>
<broker ...>
<plugins>
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="iniResourcePath" value="classpath:myshiro.ini"/>
</bean>
</plugins>
</broker>
</beans>
如果您願意,這可讓您將 Shiro 設定與 ActiveMQ Classic 代理程式設定分開。
shiro.ini 內嵌
如果您想要使用 ini 設定,並且您希望將所有設定都放在一個位置,您可以改為內嵌 ini 設定
<beans ...>
<broker ...>
<plugins ...>
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="iniConfig">
<value>
[main]
# Shiro object graph configuration here if desired/necessary
[users]
system = manager, system
[roles]
system = *
advisory = topic:ActiveMQ.Advisory*
</value>
</property>
</bean>
</plugins>
</broker>
</beans>
設計
Shiro 外掛程式是 BrokerPlugin,會在代理程式篩選器鏈中插入 3 個 BrokerFilter:SubjectFilter
、AuthenticationFilter
和 AuthorizationFilter
SubjectFilter
SubjectFilter
存在於代理程式篩選器鏈中所有其他與 Shiro 相關的代理程式篩選器之前。它會建構一個 Shiro Subject 執行個體,以反映代理程式用戶端,並確保 Subject
執行個體適用於所有可能需要使用 Subject
執行安全性作業的下游代理程式篩選器。
AuthenticationFilter
AuthenticationFilter
存在於代理程式篩選器鏈中的 SubjectFilter
之後。它確保代理程式用戶端 Subject
在允許鏈繼續之前,會視需要進行驗證。如果需要驗證且 Subject
未經驗證,則不會執行代理程式篩選器鏈,確保只有經過驗證的身分才能執行進一步的行為。
AuthorizationFilter
AuthorizationFilter
存在於代理程式篩選器鏈中的 AuthenticationFilter
之後。它確保與篩選器鏈相關聯的 Subject
已獲得授權 (允許) 執行嘗試的動作,然後才允許執行該動作。
例如,它會確保 Subject
獲准將訊息傳送至特定的主題,然後才允許執行傳送作業。如果啟用授權,而且 Subject
未經授權執行所需的動作,則不會執行代理程式篩選器鏈。
SubjectFilter
ShiroPlugin 在代理程式篩選器鏈中所有其他與 Shiro 相關的代理程式篩選器之前安裝並執行 SubjectFilter
。SubjectFilter
會建構一個 Shiro Subject 執行個體,以反映代理程式用戶端,並確保 Subject
執行個體適用於所有可能需要使用 Subject
執行安全性作業的下游代理程式篩選器。
SubjectFilter
大部分是 SubjectFilter 的「幕後」元件,但它確實為進階使用案例提供了一些自訂功能
- 透過
ConnectionSubjectFactory
自訂代理程式用戶端的Subject
執行個體建立方式的能力,以及 - 自訂 ActiveMQ Classic ConnectionContext 的 SecurityContext 建構方式的能力。
除非您非常熟悉 ActiveMQ Classic 的安全性模型,否則您可以安全地跳到下方的驗證。
ConnectionSubjectFactory
ConnectionSubjectFactory
會建立一個 Subject
執行個體,以表示代理程式用戶端的身分。 SubjectFilter
的預設執行個體是 DefaultConnectionSubjectFactory
大多數 ConnectionSubjectFactory
的實作通常會直接使用 Shiro 的 Subject.Builder
來建立一個匿名的 Subject 實例,並讓下游的 AuthenticationFilter
根據與連線相關的任何憑證來驗證 Subject。驗證後,Subject 將具有身份,這是大多數連線客戶端預期的流程。
然而,如果連線中有其他可以檢查的資料,可用於建立 Subject 實例,而不僅限於 DefaultConnectionSubjectFactory
所提供的功能,您可以實作 ConnectionSubjectFactory
介面,並將其插入到 SubjectFilter
中。
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="subjectFilter.connectionSubjectFactory">
<bean class="com.my.ConnectionSubjectFactory" .../>
</property>
</bean>
SecurityContextFactory
與訊息中介軟體用戶端連線相關的 ActiveMQ Classic ConnectionContext
會使用一個 SecurityContext
物件。當 SubjectFilter
執行時,它需要建立一個 Shiro 特有的 SecurityContext
,並將其與 ConnectionContext
關聯,以便可以在下游存取 Subject 以進行後續所有的安全性操作。
SubjectFilter
會將 SecurityContext
的建立委派給 SecurityContextFactory
實例。DefaultSecurityContextFactory
的實作會根據連線相關的 Subject
回傳 SubjectSecurityContext
實例。更改此設定應該是非常罕見的情況,但如果您必須設定自訂的 SecurityContextFactory
,您可以按照以下方式操作。
<bean id="shiroPlugin" class="org.apache.activemq.shiro.ShiroPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="subjectFilter.securityContextFactory">
<bean class="com.my.SecurityContextFactory" .../>
</property>
</bean>
請注意,此外掛程式的大部分功能和下游篩選器都期望所建立的 SecurityContext
實例為 SubjectSecurityContext
實例。
驗證
ShiroPlugin 會在訊息中介軟體篩選器鏈中緊接著 SubjectFilter
之後安裝 AuthenticationFilter
。AuthenticationFilter
確保在允許鏈繼續之前,必要時驗證訊息中介軟體用戶端的 Subject
。如果需要驗證且 Subject
未經驗證,則訊息中介軟體篩選器鏈將不會執行,確保只有經過驗證的身份才能執行進一步的行為。
工作中 - 仍在撰寫中