Security in Spring Integration
安全性是任何现代企业(或云)应用程序中的重要功能之一。此外,它对于 Enterprise Integration Patterns 中构建的分布式系统(如那些基于)也很重要。通过消息独立性和松散耦合,目标系统可以使用消息“有效负载”中的任何类型数据相互通信。我们可以信任所有这些消息,或者可以保护我们的服务以防止“感染”消息。
Security is one of the important functions in any modern enterprise (or cloud) application.
Moreover, it is critical for distributed systems, such as those built on Enterprise Integration Patterns.
Messaging independence and loose coupling let target systems communicate with each other with any type of data in the message’s payload
.
We can either trust all those messages or secure our service against “infecting” messages.
从 |
Starting with version |
Securing channels
要在集成流中保护消息通道,必须在这些通道中添加 AuthorizationChannelInterceptor
,否则可以将其配置为带有相应模式的全局通道拦截器:
To secure message channels in the integration flow, an AuthorizationChannelInterceptor
has to be added to those channels, or it can be configured as a global channel interceptor with respective pattern:
-
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>
有关更多信息,请参见 Global Channel Interceptor Configuration。
See Global Channel Interceptor Configuration for more information.
Security Context Propagation
为了确保我们与应用程序的交互按照其安全系统规则是安全的,我们应提供一些带有身份验证(主体)对象的安全性上下文。Spring Security 项目提供了一个灵活的规范机制,可以在 HTTP、WebSocket 或 SOAP 协议上对我们的应用程序客户端进行身份验证(使用简单的 Spring Security 扩展,可以对其他任何与集成协议进行身份验证)。它还提供一个 SecurityContext
,以对应用程序对象(如消息通道)进行进一步的授权检查。默认情况下,SecurityContext
通过使用 (ThreadLocalSecurityContextHolderStrategy
) 绑定到当前 Thread
的执行状态。它可通过面向切面的编程 (AOP) 拦截器访问安全方法,以检查(例如)调用者的 principal
是否有足够的权限来调用该方法。这适用于当前线程。不过,通常,处理逻辑可以在另一个线程、多个线程甚至外部系统上执行。
To be sure that our interaction with the application is secure, according to its security system rules, we should supply some security context with an authentication (principal) object.
The Spring Security project provides a flexible, canonical mechanism to authenticate our application clients over HTTP, WebSocket, or SOAP protocols (as can be done for any other integration protocol with a simple Spring Security extension).
It also provides a SecurityContext
for further authorization checks on the application objects, such as message channels.
By default, the SecurityContext
is tied to the execution state of the current Thread
by using the (ThreadLocalSecurityContextHolderStrategy
).
It is accessed by an AOP (Aspect-oriented Programming) interceptor on secured methods to check (for example) whether that principal
of the invocation has sufficient permissions to call that method.
This works well with the current thread.
Often, though, processing logic can be performed on another thread, on several threads, or even on external systems.
如果我们的应用程序是基于 Spring Integration 组件及其消息通道构建的,那么标准线程绑定行为很容易配置。在这种情况下,受保护的对象可以是任何服务激活器或转换器,它们用一个 MethodSecurityInterceptor
保护,在它们的 <request-handler-advice-chain>
中(参见 Adding Behavior to Endpoints)甚至 MessageChannel
中(参见 Securing channels,前面)。在使用 DirectChannel
通信时, SecurityContext
会自动可用,因为下游流在当前线程中运行。然而,在 QueueChannel
、 ExecutorChannel
和 PublishSubscribeChannel
的情况下,其 Executor
会按这些通道的性质将消息从一个线程传输到另一个(或几个)线程。为了支持这样的场景,我们有两个选择:
Standard thread-bound behavior is easy to configure if our application is built on the Spring Integration components and its message channels.
In this case, the secured objects can be any service activator or transformer, secured with a
MethodSecurityInterceptor
in their <request-handler-advice-chain>
(see Adding Behavior to Endpoints) or even MessageChannel
(see Securing channels, earlier).
When using DirectChannel
communication, the SecurityContext
is automatically available, because the downstream flow runs on the current thread.
However, in the cases of the QueueChannel
, ExecutorChannel
, and PublishSubscribeChannel
with an Executor
, messages are transferred from one thread to another (or several) by the nature of those channels.
In order to support such scenarios, we have two choices:
-
Transfer an
Authentication
object within the message headers and extract and authenticate it on the other side before secured object access. -
Propagate the
SecurityContext
to the thread that receives the transferred message.
这在 spring-security-messaging
模块中实现为`org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptor`,可以添加到任何 MessageChannel
或配置为 @GlobalChannelInterceptor
。此拦截器的逻辑基于从当前线程中提取 SecurityContext
(从 preSend()
方法)及其从 postReceive()
(beforeHandle()
) 方法填充到另一个线程。有关更多信息,请参阅 SecurityContextPropagationChannelInterceptor
Javadoc。
This is implemented as a org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptor
in the spring-security-messaging
module, which can be added to any MessageChannel
or configured as a @GlobalChannelInterceptor
.
The logic of this interceptor is based on the SecurityContext
extraction from the current thread (from the preSend()
method) and its populating to another thread from the postReceive()
(beforeHandle()
) method.
See the SecurityContextPropagationChannelInterceptor
Javadocs for more information.
SecurityContext
的传播和填充只是这项工作的一半。由于消息不是消息流中线程的所有者,并且系统应确保它已针对任何传入的消息受到保护,因此必须从 ThreadLocal
清除 SecurityContext
。SecurityContextPropagationChannelInterceptor
提供 afterMessageHandled()
拦截器方法实现。它通过在该传播主体调用时释放线程来清除操作。这意味着,当处理移交消息的线程完成处理消息(不管成功与否)后,将清除上下文,以便在处理另一条消息时不会无意中使用它。
Propagation and population of SecurityContext
is just one half of the work.
Since the message is not an owner of the threads in the message flow, and the system should be sure that it is secured against any incoming messages, the SecurityContext
has to be cleaned up from ThreadLocal
.
The SecurityContextPropagationChannelInterceptor
provides the afterMessageHandled()
interceptor method implementation.
It cleans up operation by freeing the thread at the end of invocation from that propagated principal.
This means that, when the thread that processes the handed-off message finishes processing the message (successful or otherwise), the context is cleared so that it cannot inadvertently be used when processing another message.
当使用 asynchronous gateway 时,你应该使用 Spring Security Concurrency Support 中的一个合适的 When working with an asynchronous gateway, you should use an appropriate
|