此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

安全性是任何现代企业(或云)应用程序中的重要功能之一。 此外,它对于分布式系统(例如基于企业集成模式构建的系统)至关重要。 消息传递独立性和松耦合使目标系统能够与消息中的任何类型的数据进行通信。 我们可以信任所有这些消息,也可以保护我们的服务免受“感染”消息的侵害。payloadSpring中文文档

从版本开始,整个模块被删除,取而代之的是更常见的库提出的 API。6.3spring-integration-securityspring-security-messaging
从版本开始,整个模块被删除,取而代之的是更常见的库提出的 API。6.3spring-integration-securityspring-security-messaging

保护通道

为了保护集成流中的消息通道,必须向这些通道添加一个,或者可以将其配置为具有相应模式的全局通道拦截器:AuthorizationChannelInterceptorSpring中文文档

@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中文文档

安全上下文传播

为了确保我们与应用程序的交互是安全的,根据其安全系统规则,我们应该提供一些带有身份验证(主体)对象的安全上下文。 Spring Security 项目提供了一种灵活的规范机制,通过 HTTP、WebSocket 或 SOAP 协议对我们的应用程序客户端进行身份验证(就像任何其他使用简单的 Spring Security 扩展的集成协议一样)。 它还提供对应用程序对象(如消息通道)的进一步授权检查。 默认情况下,使用 () 将 绑定到当前 的执行状态。 它由安全方法上的 AOP(面向方面编程)拦截器访问,以检查(例如)调用是否具有足够的权限来调用该方法。 这适用于当前线程。 但是,通常可以在另一个线程、多个线程甚至外部系统上执行处理逻辑。SecurityContextSecurityContextThreadThreadLocalSecurityContextHolderStrategyprincipalSpring中文文档

如果我们的应用程序是基于 Spring Integration 组件及其消息通道构建的,则标准线程绑定行为很容易配置。 在这种情况下,受保护的对象可以是任何服务激活器或转换器,在其中使用 (请参阅向终结点添加行为) 甚至 (请参阅前面的保护通道) 进行保护。 使用通信时,会自动可用,因为下游流在当前线程上运行。 但是,在 、 和 的情况下,消息会根据这些通道的性质从一个线程传输到另一个(或多个)线程。 为了支持此类方案,我们有两个选择:MethodSecurityInterceptor<request-handler-advice-chain>MessageChannelDirectChannelSecurityContextQueueChannelExecutorChannelPublishSubscribeChannelExecutorSpring中文文档

  • 在邮件头中传输对象,并在另一端提取并对其进行身份验证,然后再进行安全对象访问。AuthenticationSpring中文文档

  • 将 传播到接收传输消息的线程。SecurityContextSpring中文文档

这在模块中作为 a 实现,可以添加到任何模块中或配置为 . 此侦听器的逻辑基于从当前线程(从方法)中提取并将其从 () 方法填充到另一个线程。 有关更多信息,请参阅 Javadocs。org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptorspring-security-messagingMessageChannel@GlobalChannelInterceptorSecurityContextpreSend()postReceive()beforeHandle()SecurityContextPropagationChannelInterceptorSpring中文文档

繁殖和人口只是工作的一半。 由于消息不是消息流中线程的所有者,并且系统应确保它针对任何传入消息进行保护,因此必须从 中清除 。 提供拦截器方法实现。 它通过在调用结束时从传播的主体中释放线程来清理操作。 这意味着,当处理传递消息的线程完成对消息的处理(成功或其他)时,将清除上下文,以便在处理另一条消息时不会无意中使用它。SecurityContextSecurityContextThreadLocalSecurityContextPropagationChannelInterceptorafterMessageHandled()Spring中文文档

使用异步网关时,应使用 Spring Security Concurrency Support 中的适当实现,以确保通过网关调用进行安全上下文传播。 以下示例演示如何执行此操作:AbstractDelegatingSecurityContextSupportSpring中文文档

@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);

}

使用异步网关时,应使用 Spring Security Concurrency Support 中的适当实现,以确保通过网关调用进行安全上下文传播。 以下示例演示如何执行此操作:AbstractDelegatingSecurityContextSupportSpring中文文档

@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);

}