here is the demo for your reference. i tested it under win7 + vs2010 + client-server-on-same-machine.
server side:
[ServiceContract(Name="CalculatorService")]
public interface ICalculatorService {
[OperationContract]
int Add(int x, int y);
}
public class CalculatorService : ICalculatorService {
public Int32 Add(Int32 x, Int32 y) {
Console.WriteLine("{0}: service method called (x = {1}, y = {2})",
Thread.CurrentThread.ManagedThreadId, x, y);
return x + y;
}
}
class Program {
static void Main(string[] args) {
ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => true;
using (var serviceHost = new ServiceHost(typeof(CalculatorService))) {
serviceHost.Opened += delegate {
Console.WriteLine("{0}: service started",
Thread.CurrentThread.ManagedThreadId);
};
serviceHost.Open();
Console.Read();
}
}
}
<?xml version="1.0" encoding="utf-8" ?> <configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="transportSecurity">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WcfService.CalculatorService">
<endpoint address="https://hp-laptop:3721/calculatorservice"
binding="wsHttpBinding"
bindingConfiguration="transportSecurity"
contract="Contract.ICalculatorService" />
</service>
</services>
</system.serviceModel> </configuration>
Client side:
class Program {
static void Main(string[] args) {
using (var channelFactory =
new ChannelFactory<ICalculatorService>("calculatorservice")) {
ICalculatorService proxy = channelFactory.CreateChannel();
Console.WriteLine(proxy.Add(1, 2));
Console.Read();
}
Console.Read();
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="transportSecurity">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="defaultClientCertificate">
<clientCredentials>
<clientCertificate
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"
findValue="client1"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint name="calculatorservice" behaviorConfiguration="defaultClientCertificate"
address="https://hp-laptop:3721/calculatorservice"
binding="wsHttpBinding"
bindingConfiguration="transportSecurity"
contract="Contract.ICalculatorService"/>
</client>
</system.serviceModel>
</configuration>
Certificate creation:
self-created CA
makecert -n "CN=RootCA" -r -sv c:\rootca.pvk c:\rootca.cer
After creation, import this certificate into 'Trusted Root Certification' by Certificates Console. This is the step to stop the exception you mentioned.
certificate for service program
makecert -n "CN=hp-laptop" -ic c:\rootca.cer -iv c:\rootca.pvk -sr LocalMachine -ss My -pe -sky exchange
Note that the CN value above should match to the DNS part of service address. e.g. hp-laptop is my computer name. the address of service endpoint will be "https://google.com:/...". (replace google dot com with 'hp-laptop' due to some stackoverflow rules).
register service certificate with service program:
netsh http add sslcert ipport=0.0.0.0:3721 certhash=6c78ad6480d62f5f460f17f70ef9660076872326 appid={a0327398-4069-4d2d-83c0-a0d5e6cc71b5}
The certhash value is the thumbprint of service program certificate (check with Certificates Console). the appid is the GUID from service program file "AssemblyINfo.cs".
Certicate for client program:
makecert -n "CN=client1" -ic c:\rootca.cer -iv c:\rootca.pvk -sr LocalMachine -ss My -pe -sky exchange
UPDATE: according to typhoid's experience with this solution, the 'Anonymous' exception is still there due to too many trusted root authorities in that server. Two links was provided by typhoid to solve this issue.
http://support.microsoft.com/kb/2464556
http://blog.codit.eu/post/2013/04/03/Troubleshooting-SSL-client-certificate-issue-on-IIS.aspx