Spring Integration 中的安全性
安全性是任何现代企业(或云)应用程序中的重要功能之一。
此外,对于分布式系统,例如基于企业集成模式构建的系统,安全性至关重要。
消息独立性和松散耦合允许目标系统之间通过消息 payload
中的任何类型数据进行通信。
我们可以选择信任所有这些消息,或者保护我们的服务免受“感染
”消息的侵害。
从 |
保护通道
为了保护集成流中的消息通道,必须将 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 组件及其消息通道构建的,那么标准线程绑定行为很容易配置。
在这种情况下,受保护的对象可以是任何服务激活器或转换器,通过 MethodSecurityInterceptor
在其 <request-handler-advice-chain>
中进行保护(参见 为端点添加行为),甚至可以是 MessageChannel
(参见 securing-channels,上文)。
当使用 DirectChannel
通信时,SecurityContext
会自动可用,因为下游流在当前线程上运行。
然而,在 QueueChannel
、ExecutorChannel
和带有 Executor
的 PublishSubscribeChannel
的情况下,消息会根据这些通道的性质从一个线程传输到另一个线程(或多个线程)。
为了支持这些场景,我们有两种选择:
-
在消息头中传输
Authentication
对象,并在受保护对象访问之前在另一端提取并认证它。 -
将
SecurityContext
传播到接收传输消息的线程。
这在 spring-security-messaging
模块中作为 org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptor
实现,可以添加到任何 MessageChannel
或配置为 @GlobalChannelInterceptor
。
此拦截器的逻辑基于从当前线程(从 preSend()
方法)提取 SecurityContext
并将其填充到 postReceive()
(beforeHandle()
) 方法中的另一个线程。
有关更多信息,请参阅 SecurityContextPropagationChannelInterceptor
的 Javadoc。
SecurityContext
的传播和填充只是工作的一半。
由于消息不是消息流中线程的所有者,并且系统应该确保它免受任何传入消息的侵害,因此必须从 ThreadLocal
清理 SecurityContext
。
SecurityContextPropagationChannelInterceptor
提供了 afterMessageHandled()
拦截器方法的实现。
它通过在调用结束时从该传播的主体中释放线程来执行清理操作。
这意味着,当处理移交消息的线程完成消息处理(成功与否)时,上下文会被清除,以便在处理另一条消息时不会无意中被使用。
在使用 异步网关 时,您应该使用 Spring Security 并发支持 中适当的
|