Shiro

功能 > 安全性 > 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>

如您所見,與較簡單/預設設定相比,有兩件事不同

  1. [main] 區段在隱含的 iniRealm 上設定了 PasswordMatcher。這表示所有 .ini 設定的使用者都應具有適當的雜湊/安全密碼。
  2. [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 執行個體 (或 Shiro SecurityManager 執行個體) - 例如,在 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 中建構 SecurityManagerEnvironment,您可以輕鬆指定 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 個 BrokerFilterSubjectFilterAuthenticationFilterAuthorizationFilter

SubjectFilter

SubjectFilter 存在於代理程式篩選器鏈中所有其他與 Shiro 相關的代理程式篩選器之前。它會建構一個 Shiro Subject 執行個體,以反映代理程式用戶端,並確保 Subject 執行個體適用於所有可能需要使用 Subject 執行安全性作業的下游代理程式篩選器。

AuthenticationFilter

AuthenticationFilter 存在於代理程式篩選器鏈中的 SubjectFilter 之後。它確保代理程式用戶端 Subject 在允許鏈繼續之前,會視需要進行驗證。如果需要驗證且 Subject 未經驗證,則不會執行代理程式篩選器鏈,確保只有經過驗證的身分才能執行進一步的行為。

AuthorizationFilter

AuthorizationFilter 存在於代理程式篩選器鏈中的 AuthenticationFilter 之後。它確保與篩選器鏈相關聯的 Subject 已獲得授權 (允許) 執行嘗試的動作,然後才允許執行該動作。

例如,它會確保 Subject 獲准將訊息傳送至特定的主題,然後才允許執行傳送作業。如果啟用授權,而且 Subject 未經授權執行所需的動作,則不會執行代理程式篩選器鏈。

SubjectFilter

ShiroPlugin 在代理程式篩選器鏈中所有其他與 Shiro 相關的代理程式篩選器之前安裝並執行 SubjectFilterSubjectFilter 會建構一個 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 之後安裝 AuthenticationFilterAuthenticationFilter 確保在允許鏈繼續之前,必要時驗證訊息中介軟體用戶端的 Subject。如果需要驗證且 Subject 未經驗證,則訊息中介軟體篩選器鏈將不會執行,確保只有經過驗證的身份才能執行進一步的行為。

工作中 - 仍在撰寫中

Apache、ActiveMQ、Apache ActiveMQ、Apache 羽毛標誌和 Apache ActiveMQ 專案標誌是 The Apache Software Foundation 的商標。版權所有 © 2024,The Apache Software Foundation。根據 Apache License 2.0 授權。