Sending crendentials with every request

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Sending crendentials with every request

Peter Hermsdorf-2
Hi everyone,

I'm looking for a way of sending user credentials implicitly with every
remote service request.

Background: we are migrating our RCP application to RAP. That means,
multiple users are using one instance of a remote service concurrently.
(the service instance is injected via DS)

Some of these service request are depending on the user calling the
service on server side and I don't want to pollute my API by passing the
username as parameter in the service request. (that would be the last
option ...)

Any ideas or examples on how to accomplish this?

We are using the ECF generic server. I've looked into using
ISharedObjectContainerClient.setConnectInitiatorPolicy but as the name
states, that is only used when initially connecting to the server.

Thank you and all the best,
Peter




_______________________________________________
ecf-dev mailing list
[hidden email]
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/ecf-dev
Reply | Threaded
Open this post in threaded view
|

Re: Sending crendentials with every request

Scott Lewis-2
Hi Peter,

Not completely sure I understand what you are wanting to do, but you
could look at overriding these methods:


1.  On service consumer/proxy, all rpc calls go through:
org.eclipse.ecf.provider.remoteservice.generic.RegistrySharedObject.sendCallRequest(RemoteServiceRegistrationImpl,
IRemoteCall)

to asynchronously send message for remote invoke.  As part of this impl
of this, the following method is called:

sendSharedObjectMsgTo(remoteRegistration.getContainerID(),
SharedObjectMsg.createMsg(CALL_REQUEST, request));

Note the CALL_REQUEST is a String == "handleCallRequest"

2.  On service impl/host side there is this method which gets called
when CALL_REQUEST is received:

org.eclipse.ecf.provider.remoteservice.generic.RegistrySharedObject.handleCallRequest(Request)

This ends up executing the request, and calling this method to send
response back:

org.eclipse.ecf.provider.remoteservice.generic.RegistrySharedObject.sendCallResponse(ID,
Response)

which calls this method to construct and send message:

                     sendSharedObjectMsgTo(responseTarget,
SharedObjectMsg.createMsg(CALL_RESPONSE, new
Response(response.getRequestId(), getSerializableException(e))));

Note the CALL_RESPONSE is String == "handleCallResponse"

3. On service consumer/proxy this method is then called:

org.eclipse.ecf.provider.remoteservice.generic.RegistrySharedObject.handleCallResponse(Response)

If you want to add to what's sent in every rpc, you could add to the 1
(what client sends) and to 2 (what server received and how processes it)
by adding your meta-data to the Request instance that's sent (has to be
Serializable of course).

Does that help?

Thanks,

Scott

On 3/20/2020 1:14 AM, Peter Hermsdorf wrote:

> Hi everyone,
>
> I'm looking for a way of sending user credentials implicitly with
> every remote service request.
>
> Background: we are migrating our RCP application to RAP. That means,
> multiple users are using one instance of a remote service
> concurrently. (the service instance is injected via DS)
>
> Some of these service request are depending on the user calling the
> service on server side and I don't want to pollute my API by passing
> the username as parameter in the service request. (that would be the
> last option ...)
>
> Any ideas or examples on how to accomplish this?
>
> We are using the ECF generic server. I've looked into using
> ISharedObjectContainerClient.setConnectInitiatorPolicy but as the name
> states, that is only used when initially connecting to the server.
>
> Thank you and all the best,
> Peter
>
>
>
>
> _______________________________________________
> ecf-dev mailing list
> [hidden email]
> To unsubscribe from this list, visit
> https://www.eclipse.org/mailman/listinfo/ecf-dev
_______________________________________________
ecf-dev mailing list
[hidden email]
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/ecf-dev
Reply | Threaded
Open this post in threaded view
|

Re: Sending crendentials with every request

Peter Hermsdorf-2

Hi Scott,


On 21.03.2020 05:33, Scott Lewis wrote:
Not completely sure I understand what you are wanting to do, but you could look at overriding these methods:
Sometime it's not that easy to describe the use-case, but in fact your suggestions were helpful and pointed me in the right direction.

If you want to add to what's sent in every rpc, you could add to the 1 (what client sends) and to 2 (what server received and how processes it) by adding your meta-data to the Request instance that's sent (has to be Serializable of course).

Does that help?
That helped. I'm thinking about replacing

SharedObjectMsg.createMsg(CALL_REQUEST, request)

with my own class which extends SharedObjectMsg and adds the additional meta-data.

Currently I'm looking for the right place to register my own RegistrySharedObject implementation on client side (on server side i already have that).
On client side i already have a IConsumerContainerSelector with an overriden createContainer method, but haven't found a good point to intercept the object creation of RegistrySharedObject. There is a lot of Adapter and Factory stuff going on ;)

Maybe you can suggest a good solution.

Thanks,
Peter

_______________________________________________
ecf-dev mailing list
[hidden email]
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/ecf-dev
Reply | Threaded
Open this post in threaded view
|

Re: Sending crendentials with every request

Scott Lewis-2

Hi Peter,

To explain what's happening wrt the adapters, here's the stack on a client when the RegistrySharedObject is created:

Daemon Thread [RSA EndpointDescriptionLocator Dispatcher] (Suspended (breakpoint at line 25 in RemoteServiceContainerAdapterFactory))   
    owns: RemoteServiceContainerAdapterFactory  (id=100)   
    RemoteServiceContainerAdapterFactory.createAdapter(ISharedObjectContainer, Class, ID) line: 25   
    RemoteServiceContainerAdapterFactory(AbstractSharedObjectContainerAdapterFactory).getSharedObjectAdapter(ISharedObjectContainer, Class) line: 93   
    RemoteServiceContainerAdapterFactory(AbstractSharedObjectContainerAdapterFactory).getContainerAdapter(IContainer, Class) line: 51   
    RemoteServiceContainerAdapterFactory(AbstractContainerAdapterFactory).getAdapter(Object, Class) line: 32   
    AdapterManager.getAdapter(Object, String, boolean) line: 340   
    AdapterManager.loadAdapter(Object, String) line: 367   
    TCPClientSOContainer(SOContainer).getAdapter(Class) line: 298   
    ConsumerContainerSelector(AbstractConsumerContainerSelector).createContainer(ContainerTypeDescription, String, Map) line: 205   
    <stuff deleted>

You can see at bottom (ConsumerContainerSelector) that it's creating a container of a particular type (ecf.generic.client) which is passed in via the EndpointDescription sent from remote service via discovery.

The ConsumerContainerSelector.createContainer method has this call to TCPClientSOContainer.getAdapter(IRemoteServiceContainerAdapter.class);

            IRemoteServiceContainerAdapter adapter = (IRemoteServiceContainerAdapter) container
                    .getAdapter(IRemoteServiceContainerAdapter.class);

The TCPClientSOContainerAdapter.getAdapter impl has this:

        final IAdapterManager adapterManager = ProviderPlugin.getDefault().getAdapterManager();
        if (adapterManager == null)
            return null;
        return adapterManager.loadAdapter(this, adapter.getName());

Which as you can see from the stack gets the RemoteServiceContainerAdapterFactory (from org.eclipse.ecf.provider.remoteservice plugin) which ends up calling:

return new RegistrySharedObject();

In org.eclipse.ecf.provider.remoteservice.generic.RemoteServiceContainerAdapterFactory.createAdapter(ISharedObjectContainer, Class, ID)

If you were to *replace* or *extend* the TCPClientSOContainer, you should be able to circumvent the adapter manager and RemoteServiceContainerAdapterFactory/RegistrySharedObject by *overriding* the impl of:

<your container class>.getAdapter(Class adapter)

You could modify your impl of getAdapter such that instead of using the adapterManager to load an instance of RemoteServiceContainerAdapterFactory (which is associated to TCPClientSOContainer in org.eclipse.ecf.provider.remoteservice/plugin.xml) you could create an instance of your subclass of RemoteServiceContainerAdapterFactory and return the object returned from <your RemoteServiceContainerAdapterFacotry instance>.getAdapter(<your container type>.this, IRemoteServiceContainerAdapter.class) method.   The RemoteServiceContainerAdapterFactory instance>.getAdapter ends up calling createAdapter.

Your RemoteServiceContainerAdapterFactory class impl could override org.eclipse.ecf.provider.remoteservice.generic.RemoteServiceContainerAdapterFactory.createAdapter(ISharedObjectContainer, Class, ID to return a subclass of RegistryShareObject().

Does that make sense?  

Basically

a) impl <your container type>.getAdapter

b) instead of using adapter manager/plugin.xml, create your own instance of RemoteServiceContainerAdapterFactory

c) call it's getAdapter method

d) override your RemoteServiceContainerAdapterFactory.createAdapter method to return your subclass of RegistrySharedObject

Scott



On 3/23/2020 8:30 AM, Peter Hermsdorf wrote:

Hi Scott,


On 21.03.2020 05:33, Scott Lewis wrote:
Not completely sure I understand what you are wanting to do, but you could look at overriding these methods:
Sometime it's not that easy to describe the use-case, but in fact your suggestions were helpful and pointed me in the right direction.

If you want to add to what's sent in every rpc, you could add to the 1 (what client sends) and to 2 (what server received and how processes it) by adding your meta-data to the Request instance that's sent (has to be Serializable of course).

Does that help?
That helped. I'm thinking about replacing

SharedObjectMsg.createMsg(CALL_REQUEST, request)

with my own class which extends SharedObjectMsg and adds the additional meta-data.

Currently I'm looking for the right place to register my own RegistrySharedObject implementation on client side (on server side i already have that).
On client side i already have a IConsumerContainerSelector with an overriden createContainer method, but haven't found a good point to intercept the object creation of RegistrySharedObject. There is a lot of Adapter and Factory stuff going on ;)

Maybe you can suggest a good solution.

Thanks,
Peter

_______________________________________________
ecf-dev mailing list
[hidden email]
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/ecf-dev

_______________________________________________
ecf-dev mailing list
[hidden email]
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/ecf-dev
Reply | Threaded
Open this post in threaded view
|

Re: Sending crendentials with every request

Peter Hermsdorf-2

Hi Scott,

sorry for being late with my answer.

I ended up doing the following:

On client side/service consumer

* I used a custom IConsumerContainerSelector and i have overriden the createContainer(..) method to bring my own RegistrySharedObject implementation in use (I think that is similar to what you proposed just without using Adapters)

* in my custom RegistrySharedObject I have overridden the sendCallRequest(..) method and implemented a custom createRequest(..) method to have a custom Request implementation which actually adds additional metadata to the request (the username doing the request in my case)

On server side/service impl

* I already had a custom IHostContainerSelector with a custom createContainer(..) method, also to bring my custom RegistrySharedObject in place

* in that custom RegistrySharedObject I have overridden the executeRequest(..) method and a custom IProgressRunnable to process the request

* and because here I get my custom request implementation I was able to access the additional metadata easily and process the request with the additional user information (kind of a "switch user" call at server side)

After all I like this solution. Only small changes to get the work done.

Thanks again for your help!

Bye, Peter



On 25.03.2020 01:13, Scott Lewis wrote:

Hi Peter,

To explain what's happening wrt the adapters, here's the stack on a client when the RegistrySharedObject is created:

Daemon Thread [RSA EndpointDescriptionLocator Dispatcher] (Suspended (breakpoint at line 25 in RemoteServiceContainerAdapterFactory))   
    owns: RemoteServiceContainerAdapterFactory  (id=100)   
    RemoteServiceContainerAdapterFactory.createAdapter(ISharedObjectContainer, Class, ID) line: 25   
    RemoteServiceContainerAdapterFactory(AbstractSharedObjectContainerAdapterFactory).getSharedObjectAdapter(ISharedObjectContainer, Class) line: 93   
    RemoteServiceContainerAdapterFactory(AbstractSharedObjectContainerAdapterFactory).getContainerAdapter(IContainer, Class) line: 51   
    RemoteServiceContainerAdapterFactory(AbstractContainerAdapterFactory).getAdapter(Object, Class) line: 32   
    AdapterManager.getAdapter(Object, String, boolean) line: 340   
    AdapterManager.loadAdapter(Object, String) line: 367   
    TCPClientSOContainer(SOContainer).getAdapter(Class) line: 298   
    ConsumerContainerSelector(AbstractConsumerContainerSelector).createContainer(ContainerTypeDescription, String, Map) line: 205   
    <stuff deleted>

You can see at bottom (ConsumerContainerSelector) that it's creating a container of a particular type (ecf.generic.client) which is passed in via the EndpointDescription sent from remote service via discovery.

The ConsumerContainerSelector.createContainer method has this call to TCPClientSOContainer.getAdapter(IRemoteServiceContainerAdapter.class);

            IRemoteServiceContainerAdapter adapter = (IRemoteServiceContainerAdapter) container
                    .getAdapter(IRemoteServiceContainerAdapter.class);

The TCPClientSOContainerAdapter.getAdapter impl has this:

        final IAdapterManager adapterManager = ProviderPlugin.getDefault().getAdapterManager();
        if (adapterManager == null)
            return null;
        return adapterManager.loadAdapter(this, adapter.getName());

Which as you can see from the stack gets the RemoteServiceContainerAdapterFactory (from org.eclipse.ecf.provider.remoteservice plugin) which ends up calling:

return new RegistrySharedObject();

In org.eclipse.ecf.provider.remoteservice.generic.RemoteServiceContainerAdapterFactory.createAdapter(ISharedObjectContainer, Class, ID)

If you were to *replace* or *extend* the TCPClientSOContainer, you should be able to circumvent the adapter manager and RemoteServiceContainerAdapterFactory/RegistrySharedObject by *overriding* the impl of:

<your container class>.getAdapter(Class adapter)

You could modify your impl of getAdapter such that instead of using the adapterManager to load an instance of RemoteServiceContainerAdapterFactory (which is associated to TCPClientSOContainer in org.eclipse.ecf.provider.remoteservice/plugin.xml) you could create an instance of your subclass of RemoteServiceContainerAdapterFactory and return the object returned from <your RemoteServiceContainerAdapterFacotry instance>.getAdapter(<your container type>.this, IRemoteServiceContainerAdapter.class) method.   The RemoteServiceContainerAdapterFactory instance>.getAdapter ends up calling createAdapter.

Your RemoteServiceContainerAdapterFactory class impl could override org.eclipse.ecf.provider.remoteservice.generic.RemoteServiceContainerAdapterFactory.createAdapter(ISharedObjectContainer, Class, ID to return a subclass of RegistryShareObject().

Does that make sense?  

Basically

a) impl <your container type>.getAdapter

b) instead of using adapter manager/plugin.xml, create your own instance of RemoteServiceContainerAdapterFactory

c) call it's getAdapter method

d) override your RemoteServiceContainerAdapterFactory.createAdapter method to return your subclass of RegistrySharedObject

Scott



On 3/23/2020 8:30 AM, Peter Hermsdorf wrote:

Hi Scott,


On 21.03.2020 05:33, Scott Lewis wrote:
Not completely sure I understand what you are wanting to do, but you could look at overriding these methods:
Sometime it's not that easy to describe the use-case, but in fact your suggestions were helpful and pointed me in the right direction.

If you want to add to what's sent in every rpc, you could add to the 1 (what client sends) and to 2 (what server received and how processes it) by adding your meta-data to the Request instance that's sent (has to be Serializable of course).

Does that help?
That helped. I'm thinking about replacing

SharedObjectMsg.createMsg(CALL_REQUEST, request)

with my own class which extends SharedObjectMsg and adds the additional meta-data.

Currently I'm looking for the right place to register my own RegistrySharedObject implementation on client side (on server side i already have that).
On client side i already have a IConsumerContainerSelector with an overriden createContainer method, but haven't found a good point to intercept the object creation of RegistrySharedObject. There is a lot of Adapter and Factory stuff going on ;)

Maybe you can suggest a good solution.

Thanks,
Peter

_______________________________________________
ecf-dev mailing list
[hidden email]
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/ecf-dev