>>>
We generally don't
do this by default as we usually want all the tokens used by that proxy to get
garbage collected when the client is discarded.   Anything stored on the
endpoint would just "go away". 
>>>
Understand. If the proxy is instantiated by spring with default scope, it won't 
be removed as long as the bus is up and running. But we have to be careful that 
the TokenStore is not filled with a lot of expired tokens.

>>>
We'd have to dig into the code a little more to check that.
>>>
I think so too. I've now debugged my code because I noticed that my 
intermediary always sends the cached token which has been issued on behalf of 
the first user who triggered the outbound call.

My application looks like this. A user is logged in to a web application and a 
SAML token is stored in the thread local storage (till to this stage, it's CXF 
independent). A custom callback handler is configured for the STSClient to 
provide the STSClient the SAML token:
<property name="onBehalfOf" ref="delegationCallbackHandler" />

Now, the IssuedTokenInterceptorProvider is called:

...
        public void handleMessage(Message message) throws Fault {
            AssertionInfoMap aim = message.get(AssertionInfoMap.class);
            // extract Assertion information
            if (aim != null) {
                Collection<AssertionInfo> ais = 
aim.get(SP12Constants.ISSUED_TOKEN);
                if (ais == null || ais.isEmpty()) {
                    return;
                }
                if (isRequestor(message)) {
                    IssuedToken itok = 
(IssuedToken)ais.iterator().next().getAssertion();
                    
                    SecurityToken tok = retrieveCachedToken(message);
                    if (tok == null) {

...

        private SecurityToken retrieveCachedToken(Message message) {
            boolean cacheIssuedToken = 
                MessageUtils.getContextualBoolean(
                    message, SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, 
true
                );
            SecurityToken tok = null;
            if (cacheIssuedToken) {
                tok = 
(SecurityToken)message.getContextualProperty(SecurityConstants.TOKEN);
                if (tok == null) {
                    String tokId = 
(String)message.getContextualProperty(SecurityConstants.TOKEN_ID);
                    if (tokId != null) {
                        tok = getTokenStore(message).getToken(tokId);
                    }
                }
            }
            return tok;
        }

The problem is that the check whether there is already a token cached 
(retrieveCachedToken) doesn't consider the current user context. It doesn't 
check is there a token cached for the user xyz. This information can be 
retrieved only if the delegation callback handler is called first or we check 
the WebServiceContext.

What do you think?

Thanks
Oli


________________________________________
Von: Daniel Kulp [[email protected]]
Gesendet: Freitag, 18. November 2011 15:40
Bis: [email protected]
Cc: Oliver Wulff
Betreff: Re: AW: Proxy object used in multi threaded case

On Friday, November 18, 2011 10:39:19 AM Oliver Wulff wrote:
> Maybe one other point to consider is the way how the
> IssuedTokenInterceptorProvider handles the TokenStore...
>
>     static final TokenStore getTokenStore(Message message) {
>         EndpointInfo info =
> message.getExchange().get(Endpoint.class).getEndpointInfo(); synchronized
> (info) {
>             TokenStore tokenStore =
> (TokenStore)message.getContextualProperty(TokenStore.class.getName()); if
> (tokenStore == null) {
>                 tokenStore =
> (TokenStore)info.getProperty(TokenStore.class.getName()); }
>             if (tokenStore == null) {
>                 tokenStore = new MemoryTokenStore();
>                 info.setProperty(TokenStore.class.getName(), tokenStore);
>             }
>             return tokenStore;
>         }
>     }
>
> The TokenStore is tight to the proxy object / exchange object (CXF client)
> which means if there is a pool of client objects I'd like to avoid that
> each uses its own TokenStore.
>
> IMHO, the TokenStore should be global (tight to the bus) and get at
> invocation time a client object of a pool for performance reasons.

You can do that already.   If you notice:

message.getContextualProperty(TokenStore.class.getName())

it's checking for a contextual property.   Thus, you can configure a
TokenStore on the bus and it will be picked up and used.   We generally don't
do this by default as we usually want all the tokens used by that proxy to get
garbage collected when the client is discarded.   Anything stored on the
endpoint would just "go away".

Also, the TokenStore has a couple synchronized things it (to handle expires
and such) and having a BUNCH of things using a single token store when they
don't need to COULD introduce another choke point.

The other thing to be careful of is if you can have Tokens then used by other
services/clients that shouldn't be using them.    We'd have to dig into the
code a little more to check that.

Dan


>
> Thanks
> Oli
> ________________________________________
> Von: Oliver Wulff [[email protected]]
> Gesendet: Freitag, 18. November 2011 09:00
> Bis: [email protected]
> Betreff: AW: Proxy object used in multi threaded case
>
> Can anybody give me a hint where to extend this functionality in CXF itself?
>
> Thanks
> Oli
>
> ________________________________________
> Von: Oliver Wulff [[email protected]]
> Gesendet: Mittwoch, 26. Oktober 2011 09:10
> Bis: [email protected]
> Betreff: AW: Proxy object used in multi threaded case
>
> Hi there
>
> >> The SecureConv and IssuedToken interceptors current "sync" on the
> >> client
> >> object to make sure this case works.   It definitely can be a
> >> performance issue though.
>
> I guess you mean this:
>
>      STSClient client = STSUtils.getClient(message, "sts", itok);
>                         AddressingProperties maps =
>                             (AddressingProperties)message
>
> .get("javax.xml.ws.addressing.context.outbound"); if (maps == null) {
>                             maps = (AddressingProperties)message
>                                 .get("javax.xml.ws.addressing.context");
>                         }
>                         synchronized (client) {
>                             try {
>
>
> I was thinking of using Apache Commons Pool for the proxy objects. But
> before starting, I wanted to double check whether there are better ways
> thus I could contribute the enhancements back to the community. Maybe we
> could introduce a jaxws property for jaxws:client whether pooling should be
> used or not.
>
> What is the best place to hook this functionality in (ClientFactoryBean,
> ClientProxyFactoryBean or in the ClientProxy thus it works to inject the
> proxy object in your impl class)?
>
> Thanks
> Oli
> ________________________________________
> Von: Aki Yoshida [[email protected]]
> Gesendet: Mittwoch, 19. Oktober 2011 23:57
> Bis: [email protected]
> Betreff: Re: Proxy object used in multi threaded case
>
> 2011/10/19 Aki Yoshida <[email protected]>:
> > 2011/10/19 Daniel Kulp <[email protected]>:
> >> On Wednesday, October 19, 2011 11:00:51 AM Oliver Wulff wrote:
> >>> Hi guys
> >>>
> >>> I've got a question with respect to a deployment of CXF in an
> >>> intermediary scenario. The service implementation of the
> >>> intermediary injects the proxy instance for the target service it
> >>> will call. Of course, this is a multi threaded environment where
> >>> the service implementation gets the current user as part of the
> >>> incoming message (not ws-security).
> >>>
> >>> The target service expects to get a security token issued by the
> >>> STS. The username is expected to be set for the proxy and the
> >>> WSSUsernameCallbackHandler is configured to get the user from there.
> >>>
> >>> Here a snippet of the configuration:
> >>>    <jaxws:client
> >>>
> >>> name="{http://www.example.org/contract/DoubleIt}DoubleItTransportION
> >>> ABSTPor t" createdFromAPI="true"> <jaxws:properties>
> >>>
> >>>            <entry key="ws-security.sts.client">
> >>>
> >>>                <bean
> >>>                class="org.apache.cxf.ws.security.tru
> >>>                st.STSClient">>>>
> >>>                    <constructor-arg ref="cxf"/>
> >>>                    <property name="onBehalfOf"
> >>>
> >>> ref="delegationCallbackHandler" />
> >>>
> >>>
> >>> The implementation of the intermediary service gets the
> >>> BindingProvider and adds the username like this:
> >>>
> >>> BindingProvider.getRequestcontext().put(BindingProvider.USERNAME_PRO
> >>> PERTY, "myuser)
> >>>
> >>> Has the request context the scope of the current thread or is it
> >>> tight to the proxy instance.
> >>
> >> This is answered in the FAQ:
> >>
> >> http://cxf.apache.org/faq#FAQ-AreJAXWSclientproxiesthreadsafe%3F
> >>
> >>> If latter, an intermediary must create a new proxy per
> >>> request. If the former, what is the scope of the STSClient instance?
> >>
> >> Per proxy.
> >
> > If your service implementation is using your proxy and the number of
> > actively used configurations is small, you can pool (or cache) your
> > proxy instances in your service so that you don't need to create a new
> > proxy per call.
> >
> > For other cases where there is no choice and there is only one proxy
> > instance, it would probably be nice if CXF can introduce an option to
> > make the request/response context objects thread-local. But this may
> > be more complicated and may have some adverse effect.
>
> I didn't see Dan's faq reference explaining that this thread-local
> option is already provided.
> so, please ignore my comment.
>
> regards, aki
>
> > regards, aki
> >
> >>> If
> >>> there are several requests coming in, the proxy instance is global,
> >>> the
> >>> request context is correlated with the thread (assumption) it might
> >>> not
> >>> work because there is only one STSClient instance.
> >>
> >> The SecureConv and IssuedToken interceptors current "sync" on the
> >> client
> >> object to make sure this case works.   It definitely can be a
> >> performance issue though.
> >>
> >>
> >> --
> >> Daniel Kulp
> >> [email protected]
> >> http://dankulp.com/blog
> >> Talend - http://www.talend.com
--
Daniel Kulp
[email protected] - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com

Reply via email to