DI for IAuthorizer across remoting boundary

Posts   
 
    
mikeg22
User
Posts: 411
Joined: 30-Jun-2005
# Posted on: 03-Aug-2007 02:02:31   

From what I understand, I can set up a DI configuration so that a new entity will get a specific IAuthorizer instance injected into it when the entity is created. This is all well and good, but what if I don't want an IAuthorizer to be used on one side of a remoting boundary, but it should be used on the other side of the boundary?

Basically, I want to fetch an entity on the DAL server, remote it to the client, and while it is on the client, I want it to use an IAuthorizer instance that only exists on the client (it may need to make calls across the remoting boundary itself). When the entity is persisted, I want it to be deserialized on the DAL side without getting an IAuthorizer injected into it, and also it should not "carry along" the IAuthorizer that it used on the client side via deserialization.

I tried thinking of a way to use the DependencyInjectionScope, but couldn't make this work. Any ideas?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 03-Aug-2007 10:25:13   

DependencyInjectionScopes are used to define a section in which DI is taken place using the definitions of the scope. So if an object lives longer than the scope, the objects aren't removed.

If you want to have an authorizer only on the client, you can do two things: 1) remove the authorizer before it's being serialized. This is cumbersome 2) use a dummy authorizer on the server side, i.e. one which is simply an empty derived class of the base class so everything is allowed. Be sure the types match. (assembly name + type name).

You could get away with not having the authorizer class on the server, if you're using normal serialization: the type isn't found on the server so it's ignored. This will be slower though, as it will be an exception which is swallowed as the info.GetValue() call throws an exception (as MS didn't implement a way to peek into the info set which values it contains )

Frans Bouma | Lead developer LLBLGen Pro
mikeg22
User
Posts: 411
Joined: 30-Jun-2005
# Posted on: 03-Aug-2007 16:42:52   

So, does the DI happen when an entity is created on one side of a remoting boundary (when the entity's deserialization constructor runs), or is everything "injected" just with brand new object creation?

The reason I ask is that I wonder which DI instance is used when the authorizer is deserialized...does it just do the normal deserialization lookup of that object's type, making a new instance of that type (namespace+type) or does it use the DI confiiguration set up on this side of the remoting boundary, and inject the called-for instance at that point? Who wins, the DI mechanism creator or the deserialization creator? Or do I just not know what I'm talking about at all smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 04-Aug-2007 13:54:29   

mikeg22 wrote:

So, does the DI happen when an entity is created on one side of a remoting boundary (when the entity's deserialization constructor runs), or is everything "injected" just with brand new object creation?

When the constructor runs which isn't the case with deserialization.

Also, the reason why the authorizer is serialized is because it might be stateful.

The reason I ask is that I wonder which DI instance is used when the authorizer is deserialized...does it just do the normal deserialization lookup of that object's type, making a new instance of that type (namespace+type) or does it use the DI confiiguration set up on this side of the remoting boundary, and inject the called-for instance at that point? Who wins, the DI mechanism creator or the deserialization creator? Or do I just not know what I'm talking about at all smile

Deserialization simply creates a new instance of the type specified in the datastream and then stores the data of that object into the new instance, member by member. simple_smile

The serializer wins, so if you set the authorizer on the service and have the same types on the client available, you'll get them also on the client. That's chosen to be able to set authorizers despite the fact if DI is enabled on the client simple_smile

Frans Bouma | Lead developer LLBLGen Pro
mikeg22
User
Posts: 411
Joined: 30-Jun-2005
# Posted on: 04-Aug-2007 18:53:05   

Ok. Is there a way to configure it so that the DI runs when the deserialization constructor runs? And if yes (I'm guessing no simple_smile ) can it just run on one side of the remoting boundary, on the client side when an entity comes from the server?

My situation is that it only makes sense to use authorization on the client. On the server, security can be disregarded as there are plenty of entity-related functions which are user-ambigious. I suppose the authorizer can check its environment and only do anything if it is on the client, but this seems like a bit of a hack.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 06-Aug-2007 14:08:12   

mikeg22 wrote:

Ok. Is there a way to configure it so that the DI runs when the deserialization constructor runs? And if yes (I'm guessing no simple_smile ) can it just run on one side of the remoting boundary, on the client side when an entity comes from the server?

My situation is that it only makes sense to use authorization on the client. On the server, security can be disregarded as there are plenty of entity-related functions which are user-ambigious. I suppose the authorizer can check its environment and only do anything if it is on the client, but this seems like a bit of a hack.

On the contrary, I think it's the best solution. simple_smile The thing is: authorization is context bound, so you have to figure out the context in which you are doing authorization anyway. So if you're on the server, the authorization can be necessary sometimes (not now, but perhaps in the future) and in other situations it's not.

So you have to obtain the list of credentials per user anyway. And guess what: on the server that's a full list: everyone is allowed to do everything wink .

Frans Bouma | Lead developer LLBLGen Pro
mikeg22
User
Posts: 411
Joined: 30-Jun-2005
# Posted on: 06-Aug-2007 17:35:02   

Otis wrote:

mikeg22 wrote:

Ok. Is there a way to configure it so that the DI runs when the deserialization constructor runs? And if yes (I'm guessing no simple_smile ) can it just run on one side of the remoting boundary, on the client side when an entity comes from the server?

My situation is that it only makes sense to use authorization on the client. On the server, security can be disregarded as there are plenty of entity-related functions which are user-ambigious. I suppose the authorizer can check its environment and only do anything if it is on the client, but this seems like a bit of a hack.

On the contrary, I think it's the best solution. simple_smile The thing is: authorization is context bound, so you have to figure out the context in which you are doing authorization anyway. So if you're on the server, the authorization can be necessary sometimes (not now, but perhaps in the future) and in other situations it's not.

So you have to obtain the list of credentials per user anyway. And guess what: on the server that's a full list: everyone is allowed to do everything wink .

I had pretty much convinced myself that the context should be deciding when to use the authorization, but I admit I don't exactly know why smile

I guess I'm a big fan of keeping the decisions in the context itself, which is why I like the adapter model to begin with...there is no "magic black box code" running inside the entity deciding how to persist itself...its all there for you to see in the context.

Another reason I wanted the authorizer to just "not be there" on the server is that I don't want to set up default answers that come out of the dummy authorizer when it is running on the server. All the "Can..." functions on the dummy authorizer will have to return "true" I guess, but I would prefer the code path not even have to come to these hard-coded decisions. This is because I see the situation not as "what are the credentials per user on the server" but more that "there is no authorization on the server."

Oh well, I'll figure something out. Thanks for your help simple_smile