Saturday, April 10, 2010

.Net 2 remoting with security support.

Yes I know there is clear statement in MSDN saying this is outdated technology and I should use WCF. But if you are like me who is stuck with .NET 2 on Windows 2000, you still have to use this.

Normally I use spring.net to inject all my objects and control config through external config files, so I don't use the *.config files normal tutorials use. I need to get everything done by code. This is not hard, but needs a little search around.

Below code will create a secure tcp channel at server side:
IDictionary prop = new Hashtable();
prop["port"] = 9999;
prop["secure"] = true;
prop["impersonate"] = false; // when "secure" is true, this is by default, thus optional
TcpServerChannel tcp = new TcpServerChannel(prop, null, new AuthorizationImp()); // auth module can also be specified in property hashtable.
ChannelServices.RegisterChannel(tcp, true);

IService svc = new ServiceImp(); // this makes the server a singleton.
ObjRef or = RemotingServices.Marshal(svc, "Service");

Now the server is ready for servicing clients, under the name "tcp://localhost:9999/Service". We can build a client to connect to it:

IDictionary prop = new Hashtable();
prop["port"] = 9999;
prop["secure"] = true;
prop["tokenImpersonationLevel"] = TokenImpersonationLevel.Identification; // when "scure" is true, this is by default and also optional
IChannel tcp = new TcpClientChannel(prop, null);

ChannelServices.RegisterChannel(tcp, true);

IService svc = (IService) Activator.GetObject(typeof (IService), "tcp://localhost:9999/Service");

IDictionary csp = ChannelServices.GetChannelSinkProperties(svc);

svc.Repeat("From client", 5); // call with default login

csp["username"] = "rrr"; // now use another user to call
csp["password"] = "rrr";
svc.Repeat("From client", 5);

csp["username"] = "mmm"; // another
csp["password"] = "mmm";
svc.Repeat("From client", 5);

From the code you might have figured out that IService is a interface used by both server and client to decouple a concrete dependency to any implementation. It has only 1 method called Repeat.

So how does server know who is calling for service? Even without impersonation, the server code can still retrieve the caller's identity by Thread.CurrentPrincipal.Identity.But the WindowsIdentity.GetCurrent() will still return the current user the process is running on. MSDN made a mistake at this point.

No comments:

Post a Comment