问题
I have some perplexity about the SecurityContext propagation in Spring Integration.
Here is the point of the documentation:
http://docs.spring.io/spring-integration/reference/htmlsingle/#security-context-propagation
My perplexity are the following:
(1) 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) and it provides a SecurityContext for further authorization checks on the application objects, such as message channels. By default, the SecurityContext is tied with the current Thread's execution state using the (ThreadLocalSecurityContextHolderStrategy). It is accessed by an AOP interceptor on secured methods to check if that principal of the invocation has sufficent permissions to call that method, for example. This works well with the current thread, but often, processing logic can be performed on another thread or even on several threads, or on to some external system(s).
This means that the SecurityContext (normally) is accessible only for the current Thread. Right?
So, how to make it accessible for another thread of another application (integrated with Spring Integration) ?
(2) 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 may be any service activator or transformer, secured with a
MethodSecurityInterceptor
in their (see Section 8.8, “Adding Behavior to Endpoints”) or evenMessageChannel
(see Section D.2, “Securing channels” above). When using DirectChannel communication, the SecurityContext is available automatically, because the downstream flow runs on the current thread. But in case 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 can either transfer an Authentication object within the message headers and extract and authenticate it on the other side before secured object access. Or, we can propagate the SecurityContext to the thread receiving the transferred message.
This means that we have to extract the Principal manually? If yes, how?
Or it's enough to use the propagation aspect, from 4.2 version?
(3) Starting with version 4.2 SecurityContext propagation has been introduced. It is implemented as a
SecurityContextPropagationChannelInterceptor
, which can simply be added to anyMessageChannel
or configured as a@GlobalChannelInterceptor
. The logic of this interceptor is based on the SecurityContext extraction from the current thread from thepreSend()
method, and its populating to another thread from thepostReceive()
(beforeHandle()) method. Actually, this interceptor is an extension of the more generic ThreadStatePropagationChannelInterceptor, which wraps the message-to-send together with the state-to-propagate in an internal Message extension - MessageWithThreadState, - on one side and extracts the original message back and state-to-propagate on another. The ThreadStatePropagationChannelInterceptor can be extended for any context propagation use-case and SecurityContextPropagationChannelInterceptor is a good sample on the matter.
"Starting with version 4.2 SecurityContext propagation has been introduced." => Ok, very well.
But: "It is implemented as a SecurityContextPropagationChannelInterceptor, which can simply be added to any MessageChannel or configured as a @GlobalChannelInterceptor."
What does it mean? I have to implement an interceptor that extends "SecurityContextPropagationChannelInterceptor" ?
What I have to "add" in my <int:channel>
configuration?
And if I use <int:channel-interceptor>
(the same of @GlobalChannelInterceptor), it's different from using <int:interceptors>
?
Other perplexity:
"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."
But why there are a "obtainPropagatingContext"
method and a "populatePropagatedContext"
method in the SecurityContextPropagationChannelInterceptor
class?
Where is made the propagation? In the preSend() / postReceive() methods, or in those two methods?
Furthermore, I tried to propagate the SecurityContext to an external application, without success...
Any explanations about this argument would be appreciated.
回答1:
You have a lot of questions here, but let me try to answer to them.
- What does it mean? I have to implement an interceptor that extends "SecurityContextPropagationChannelInterceptor" ?
No, there is such an interceptor in the Framework out-of-the-box. What you have to do to understand how to add interceptor to MessageChannel
: http://docs.spring.io/spring-integration/reference/html/messaging-channels-section.html#channel-configuration-interceptors.
Or like this:
@Bean
@GlobalChannelInterceptor(patterns = {
"#{'queueChannel'}",
"${security.channel:executorChannel}",
"publishSubscribeChannel" })
public ChannelInterceptor securityContextPropagationInterceptor() {
return new SecurityContextPropagationChannelInterceptor();
}
See their JavaDocs for more information.
- But why there are a "obtainPropagatingContext" method and a "populatePropagatedContext" method in the SecurityContextPropagationChannelInterceptor class?
SecurityContextPropagationChannelInterceptor extends ThreadStatePropagationChannelInterceptor<Authentication>
, where obtainPropagatingContext
and populatePropagatedContext
are just generic method to extract some current State
in the preSend()
(on Thread) and provide that State
for population/manipulation in the postReceive()
, which may happen in the different Thread.
- Yes,
SecurityContext
is thread-bound in Spring Security and the logic to be sure that we can perform a secured function is fully based on theThreadLocal
variable. That's why we have to transfer it that way. The "propagation" is a process not state.
Not sure what you mean about "external application", but there is only one mechanism to do that: send credentials together with the request to that application.
来源:https://stackoverflow.com/questions/38441013/spring-integration-the-securitycontext-propagation