Spring Integration 中的安全性

安全性是任何現代企業(或雲)應用程式中的重要功能之一。此外,對於分散式系統(例如基於企業整合模式構建的系統)而言,它至關重要。訊息獨立性和鬆散耦合允許目標系統使用訊息 payload 中的任何型別資料相互通訊。我們可以信任所有這些訊息,或者保護我們的服務免受“感染”訊息的侵害。

從版本 6.3 開始,整個 spring-integration-security 模組已被移除,取而代之的是更常見的 spring-security-messaging 庫提供的 API。

保護通道

為了保護整合流中的訊息通道,必須將 AuthorizationChannelInterceptor 新增到這些通道中,或者可以將其配置為具有相應模式的全域性通道攔截器。

  • Java

  • XML

@Bean
@GlobalChannelInterceptor(patterns = "secured*")
AuthorizationChannelInterceptor authorizationChannelInterceptor() {
    return new AuthorizationChannelInterceptor(AuthorityAuthorizationManager.hasAnyRole("ADMIN", "PRESIDENT"));
}
<channel-interceptor pattern="securedChannel*">
    <beans:bean class="org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor">
        <beans:constructor-arg>
            <beans:bean class="org.springframework.security.authorization.AuthorityAuthorizationManager"
                        factory-method="hasAnyRole">
                <beans:constructor-arg>
                    <beans:array>
                        <beans:value>ADMIN</beans:value>
                        <beans:value>PRESIDENT</beans:value>
                    </beans:array>
                </beans:constructor-arg>
            </beans:bean>
        </beans:constructor-arg>
    </beans:bean>
</channel-interceptor>

有關更多資訊,請參閱 全域性通道攔截器配置

安全上下文傳播

為了確保我們與應用程式的互動是安全的,根據其安全系統規則,我們應該提供一個帶有身份驗證(主體)物件的安全上下文。Spring Security 專案提供了一個靈活的、規範的機制,用於透過 HTTP、WebSocket 或 SOAP 協議(透過簡單的 Spring Security 擴充套件,也可以用於任何其他整合協議)對我們的應用程式客戶端進行身份驗證。它還為應用程式物件(例如訊息通道)上的進一步授權檢查提供了 SecurityContext。預設情況下,SecurityContext 透過使用 (ThreadLocalSecurityContextHolderStrategy) 繫結到當前 Thread 的執行狀態。它透過安全方法上的 AOP(面向切面程式設計)攔截器訪問,以檢查(例如)呼叫的 principal 是否具有足夠的許可權來呼叫該方法。這在當前執行緒中執行良好。然而,通常處理邏輯可以在另一個執行緒、多個執行緒甚至外部系統上執行。

如果我們的應用程式是基於 Spring Integration 元件及其訊息通道構建的,則標準執行緒繫結行為很容易配置。在這種情況下,受保護的物件可以是任何服務啟用器或轉換器,透過其 <request-handler-advice-chain> 中的 MethodSecurityInterceptor(請參閱 向端點新增行為)甚至 MessageChannel(請參閱前面的 保護通道)進行保護。當使用 DirectChannel 通訊時,SecurityContext 自動可用,因為下游流在當前執行緒上執行。然而,在 QueueChannelExecutorChannel 和帶有 ExecutorPublishSubscribeChannel 的情況下,訊息由於這些通道的性質而從一個執行緒傳輸到另一個執行緒(或多個執行緒)。為了支援此類場景,我們有兩種選擇:

  • 在訊息頭中傳輸 Authentication 物件,並在訪問受保護物件之前在另一側提取並驗證它。

  • SecurityContext 傳播到接收已傳輸訊息的執行緒。

這在 spring-security-messaging 模組中實現為 org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptor,可以將其新增到任何 MessageChannel 或配置為 @GlobalChannelInterceptor。此攔截器的邏輯基於從當前執行緒(從 preSend() 方法)提取 SecurityContext 並從 postReceive() (beforeHandle()) 方法將其填充到另一個執行緒。有關更多資訊,請參閱 SecurityContextPropagationChannelInterceptor Javadoc。

SecurityContext 的傳播和填充只是工作的一半。由於訊息不是訊息流中執行緒的所有者,並且系統應該確保它免受任何傳入訊息的侵害,因此必須從 ThreadLocal 清除 SecurityContextSecurityContextPropagationChannelInterceptor 提供了 afterMessageHandled() 攔截器方法實現。它透過在呼叫結束時從傳播的主體中釋放執行緒來執行清理操作。這意味著,當處理已移交訊息的執行緒完成訊息處理(成功或失敗)時,上下文將被清除,以免在處理另一條訊息時無意中使用。

在使用 非同步閘道器 時,您應該使用 Spring Security 併發支援 中適當的 AbstractDelegatingSecurityContextSupport 實現,以確保安全上下文透過閘道器呼叫進行傳播。以下示例展示瞭如何實現:

@Configuration
@EnableIntegration
@IntegrationComponentScan
public class ContextConfiguration {

    @Bean
    public AsyncTaskExecutor securityContextExecutor() {
        return new DelegatingSecurityContextAsyncTaskExecutor(
                         new SimpleAsyncTaskExecutor());
    }

}

@MessagingGateway(asyncExecutor = "securityContextExecutor")
public interface SecuredGateway {

    @Gateway(requestChannel = "queueChannel")
    Future<String> send(String payload);

}
© . This site is unofficial and not affiliated with VMware.