Simple custom secured WCF
1Hancock posted on 2016/01/23 13:15:14
Introduction
WCF is a good technology for client/server application modal. But it rather complex to make it become secured. And sometime, your application just requires to make a simple authorize (like only user/password, .. ) without SSL. You can use ClearUsernameBinding. And now you will have a new solution. In my opinion, this is more simple.
Background
To configuration a secured WCF sometimes is a terrible task for a new WCF developer. And one of the big problems is about server certificate. Instead of that, we all want our WCF service becomes a secured one with a simple binding. So today, I want to introduce you a very simple way to make your normal WCF service become secured (enough for you normal task). For advance users, you can customize the code to make it more secured.
Basic Ideas
The basic idea of the solution is creating a message inspector
Client
+ Read the configuration file to get user name, password
+ Generate a secured key (SK) base on client system time
+ Encrypt user name, password with SK
+ Generate a token key (TK)
+ Encrypt TK with SK to become certificated key (CK)
+ Sending user name, password, TK, CK to the server
Server
+ Generate a secured key (SK) base on server system time
+ Try to decrypt CK, and compare with TK. If they are the same, SK is ok.
+ If failed, try to create more 4 SK with different nearest time. If they are all failed, throw unauthorized exception
+ If SK is ok, decrypt user name, password, and get the remote ip
+ Read the configuration file to get legal user names, passwords, remote ips
+ If the client user name, password, ip are correct, continue the message as normal
+ If one of them is invalid, throw unauthorized exception
One more idea is authentication with a signed assembly. That means, the WCF server can decide which assembly can request the WCF service (base on the public key of the signed assembly).
How to use the code
Server side:
C# code
and configuration file WcfPolicy.config:
Client side:
C# code
and configuration file WcfPolicy.config:
Points of Interest
I found it very difficulty to explain what I had done in the code and I didn't know which point was hard to understand. I am a good "worker" not a good "teacher". Please don't hesitate to ask me anything that you don't understand.
WCF is a good technology for client/server application modal. But it rather complex to make it become secured. And sometime, your application just requires to make a simple authorize (like only user/password, .. ) without SSL. You can use ClearUsernameBinding. And now you will have a new solution. In my opinion, this is more simple.
Background
To configuration a secured WCF sometimes is a terrible task for a new WCF developer. And one of the big problems is about server certificate. Instead of that, we all want our WCF service becomes a secured one with a simple binding. So today, I want to introduce you a very simple way to make your normal WCF service become secured (enough for you normal task). For advance users, you can customize the code to make it more secured.
Basic Ideas
The basic idea of the solution is creating a message inspector
class SecuredMessageHeaders : IClientMessageInspector ,IDispatchMessageInspector { ... ... ... } [AttributeUsage(AttributeTargets.Interface)] public sealed class SecuredService : Attribute, IContractBehavior { #region IContractBehavior Members public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { return; } public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new SecuredMessageHeaders(_policyFile)); return; } public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { dispatchRuntime.MessageInspectors.Add(new SecuredMessageHeaders(_policyFile)); return; } public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { } #endregion }
Client
+ Read the configuration file to get user name, password
+ Generate a secured key (SK) base on client system time
+ Encrypt user name, password with SK
+ Generate a token key (TK)
+ Encrypt TK with SK to become certificated key (CK)
+ Sending user name, password, TK, CK to the server
Server
+ Generate a secured key (SK) base on server system time
+ Try to decrypt CK, and compare with TK. If they are the same, SK is ok.
+ If failed, try to create more 4 SK with different nearest time. If they are all failed, throw unauthorized exception
+ If SK is ok, decrypt user name, password, and get the remote ip
+ Read the configuration file to get legal user names, passwords, remote ips
+ If the client user name, password, ip are correct, continue the message as normal
+ If one of them is invalid, throw unauthorized exception
One more idea is authentication with a signed assembly. That means, the WCF server can decide which assembly can request the WCF service (base on the public key of the signed assembly).
How to use the code
Server side:
C# code
[ServiceContract] [SecuredService] public interface IHelloWorldService { [OperationContract] string SayHello(string msg); }
and configuration file WcfPolicy.config:
<credentials>
<credential username="[usr]" password="[pwd]" ip="legal_ip"/>
</credentials>
Client side:
C# code
[ServiceContract] [SecuredService] public interface IHelloWorldService { [OperationContract] string SayHello(string msg); }
and configuration file WcfPolicy.config:
<credentials>
<credential username="[usr]" password="[pwd]"/>
</credentials>
Points of Interest
I found it very difficulty to explain what I had done in the code and I didn't know which point was hard to understand. I am a good "worker" not a good "teacher". Please don't hesitate to ask me anything that you don't understand.