Spring 集成中的安全性
Spring 集成中的安全性
安全性是任何现代企业(或云)应用程序的重要功能之一。
此外,它对于分布式系统(例如构建在 Enterprise Integration Patterns 上的系统)至关重要。
消息收发独立性和松散耦合使目标系统能够与消息中的任何类型的数据相互通信。
我们可以信任所有这些消息,也可以保护我们的服务免受 “感染” 消息的侵害。payload
Spring 集成与 Spring Security 一起提供了一种简单而全面的方法来保护消息通道以及集成解决方案的其他部分。
从版本 6.0 开始,通过 annotation 和 XML 进行的 及其配置已被弃用,取而代之的是 从模块使用。
相应的基础设施完全涵盖了以前支持的基于角色的身份验证,此外,它还允许配置任何其他可能的授权策略。ChannelSecurityInterceptor
@SecuredChannel
<secured-channels>
AuthorizationChannelInterceptor
spring-security-messaging
AuthorizationManager
唯一剩下的 Spring 集成功能是将来也可能被提升到上述模块的功能。SecurityContextPropagationChannelInterceptor
spring-security-messaging
您需要将此依赖项包含在您的项目中:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-security</artifactId>
<version>6.1.9</version>
</dependency>
compile "org.springframework.integration:spring-integration-security:6.1.9"
保护通道
要保护集成流中的消息通道,必须将 an 添加到这些通道中,或者可以将其配置为具有相应模式的全局通道拦截器:AuthorizationChannelInterceptor
@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>
有关更多信息,请参见 Global Channel Interceptor Configuration 。
安全上下文传播
为了确保我们与应用程序的交互是安全的,根据其安全系统规则,我们应该为一些安全上下文提供一个身份验证 (principal) 对象。
Spring Security 项目提供了一种灵活的规范机制,可以通过 HTTP、WebSocket 或 SOAP 协议对我们的应用程序客户端进行身份验证(对于具有简单 Spring Security 扩展的任何其他集成协议,可以这样做)。
它还为应用程序对象(例如消息通道)提供了进一步的授权检查。
默认情况下,使用 () 将 this 绑定到当前 source 的执行状态。
它由安全方法上的 AOP(面向方面编程)拦截器访问,以检查(例如)调用是否具有调用该方法的足够权限。
这与当前线程配合得很好。
但是,通常可以在另一个线程、多个线程甚至外部系统上执行处理 logic 。SecurityContext
SecurityContext
Thread
ThreadLocalSecurityContextHolderStrategy
principal
如果我们的应用程序构建在 Spring 集成组件及其消息通道之上,那么标准的线程绑定行为很容易配置。
在这种情况下,受保护的对象可以是任何服务激活器或转换器,在其中用 a 保护(参见 向端点添加行为)甚至(参见前面的保护通道)。
使用通信时,它会自动可用,因为下游流在当前线程上运行。
但是,在 , 和 , 的情况下,消息会根据这些通道的性质从一个线程传输到另一个线程(或多个)。
为了支持此类方案,我们有两种选择:MethodSecurityInterceptor
<request-handler-advice-chain>
MessageChannel
DirectChannel
SecurityContext
QueueChannel
ExecutorChannel
PublishSubscribeChannel
Executor
-
在消息标头中传输对象,并在安全对象访问之前在另一端提取和验证它。
Authentication
-
将 传播到接收传输消息的线程。
SecurityContext
版本 4.2 引入了传播。
它以 的形式实现,您可以将其添加到任何 中或配置为 。
此拦截器的逻辑基于从当前线程(从方法)中提取,并将其从 () 方法填充到另一个线程。
实际上,这个拦截器是 更通用 的扩展 ,它一方面将要发送的消息与要传播的状态包装在内部扩展 () 中,另一方面提取原始消息和要传播的状态。
您可以扩展 for any context propagation 用例,这是一个很好的示例。SecurityContext
SecurityContextPropagationChannelInterceptor
MessageChannel
@GlobalChannelInterceptor
SecurityContext
preSend()
postReceive()
beforeHandle()
ThreadStatePropagationChannelInterceptor
Message<?>
MessageWithThreadState<S>
ThreadStatePropagationChannelInterceptor
SecurityContextPropagationChannelInterceptor
的逻辑基于消息修改(它返回一个要发送的内部对象)。
因此,在将此拦截器与任何其他也可以修改消息的拦截器结合使用时(例如,通过 ),您应该小心。
要传播的状态可能会丢失。
在大多数情况下,要解决此问题,您可以为 channel 订购拦截器,并确保 是堆栈中的最后一个拦截器。ThreadStatePropagationChannelInterceptor MessageWithThreadState MessageBuilder.withPayload(…)…build() ThreadStatePropagationChannelInterceptor |
繁殖和种群只是工作的一半。
由于消息不是消息流中线程的所有者,并且我们应该确保我们对任何传入消息都是安全的,因此我们必须清理 from .
提供了拦截器方法实现。
它通过在调用结束时从该传播的主体中释放线程来清理操作。
这意味着,当处理已传递消息的线程完成对消息的处理(成功或其他)时,将清除上下文,以便在处理另一条消息时不会无意中使用它。SecurityContext
SecurityContext
ThreadLocal
SecurityContextPropagationChannelInterceptor
afterMessageHandled()
使用异步网关时,您应该使用 Spring Security Concurrency Support 中的适当实现,以确保通过网关调用进行安全上下文传播。
以下示例显示了如何执行此操作:
|