[WCF Security] 3. X509 身份验证
每个客户端的数字证书名称和序号的组合都是唯一的,我们通过它做出相应的验证动作。4. 验证器WCF 提供了多种数字证书的验证手段,不过我们最习惯的应该还是 "Custom",因为有很多附加行为要处理。在服务器端添加一个继承自 X509CertificateValidator 的验证器。
发布日期:2021-06-29 03:54:24
浏览次数:3
分类:技术文章
本文共 7648 字,大约阅读时间需要 25 分钟。
个人认为在 Intranet / Internet 环境下,最方便的认证方式应该是 X.509 数字证书。当然,还有一个原因是我用 Windows Authentication 从来没成功过。
以下我们详细描述如何创建 "Certificate Authentication"。1. 创建数字证书一般情况下,我们为服务器以及每个客户端都单独创建一个服务器,以便标识其唯一身份。创建数字证书时,必须添加 "-pe" 和 "-sky exchange" 参数。有关数字证书更多的信息,请参考《》。 D:/>makecert -r -pe -n "CN=MyServer" -ss My -sky exchange D:/>makecert -r -pe -n "CN=Client1" -ss My -sky exchange
2. 创建服务
[ServiceContract] public interface IService { [OperationContract] string Test(); } public class MyService : IService { public string Test() { Console.WriteLine(ServiceSecurityContext.Current.PrimaryIdentity.AuthenticationType); Console.WriteLine(ServiceSecurityContext.Current.PrimaryIdentity.Name); return "Server:" + DateTime.Now.ToString(); } } public class WcfTest { public static void Test() { ServiceHost host = new ServiceHost(typeof(MyService)); host.Open(); } }
安全方式:Transport 客户端验证类型:Certificate在 serviceCredentials 中设置好证书的查找参数,同时将验证模式(certificateValidationMode) 设为 None (因为我们创建的是 "不受信任" 的证书)。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="NewBehavior"> <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8080" /> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceCredentials> <clientCertificate> <authentication certificateValidationMode="None" /> </clientCertificate> <serviceCertificate findValue="MyServer" storeLocation="CurrentUser" x509FindType="FindBySubjectName" /> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="NewBinding0"> <security mode="Transport"> <transport clientCredentialType="Certificate" /> </security> </binding> </netTcpBinding> </bindings> <services> <service behaviorConfiguration="NewBehavior" name="Learn.Library.WCF.MyService"> <endpoint address="net.tcp://localhost:8081" binding="netTcpBinding" bindingConfiguration="NewBinding0" contract="Learn.Library.WCF.IService"> </endpoint> </service> </services> </system.serviceModel> </configuration>
3. 创建客户端生成代理客户端。 using (ServiceClient client = new ServiceClient()) { Console.WriteLine(client.Test()); }
注意在配置文件中,我们在 EndPointBehaviors 中添加 ClientCredentials 来设置数字整数的相关信息。基于和上面同样的理由,我们也得将 certificateValidationMode 设为 "None"。 <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="NewBehavior"> <clientCredentials> <clientCertificate findValue="Client1" x509FindType="FindBySubjectName" /> <serviceCertificate> <authentication certificateValidationMode="None" /> </serviceCertificate> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="NetTcpBinding_IService"> <security mode="Transport"> <transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" /> <message clientCredentialType="Windows" /> </security> </binding> </netTcpBinding> </bindings> <client> <endpoint address="net.tcp://localhost:8081/" behaviorConfiguration="NewBehavior" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IService" contract="ConsoleApplication1.localhost.IService" name="NetTcpBinding_IService"> <identity> <dns value="MyServer" /> </identity> </endpoint> </client> </system.serviceModel> </configuration>
运行后,我们对比一下服务器端输出结果和Client1数字证书的信息。
public class CustomX509CertificateValidator : X509CertificateValidator { public override void Validate(X509Certificate2 certificate) { //Console.WriteLine(certificate.Subject); //Console.WriteLine(certificate.Thumbprint); if (certificate.Thumbprint != "40399ADCC90BB3C4D23D2B639D4356AABDD60091") throw new SecurityTokenException("Certificate Validation Error!"); } }
当然,配置文件也得做些调整,将 certificateValidationMode 验证改为 Custom 和我们自定义的验证类型。这回不用管它是否是 "不信任证书" 了。(客户端配置不做调整) <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="NewBehavior"> <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8080" /> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceCredentials> <clientCertificate> <authentication customCertificateValidatorType= "Learn.Library.WCF.CustomX509CertificateValidator, Learn.Library" certificateValidationMode="Custom" /> </clientCertificate> <serviceCertificate findValue="MyServer" storeLocation="CurrentUser" x509FindType="FindBySubjectName" /> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="NewBinding0"> <security mode="Transport"> <transport clientCredentialType="Certificate" /> </security> </binding> </netTcpBinding> </bindings> <services> <service behaviorConfiguration="NewBehavior" name="Learn.Library.WCF.MyService"> <endpoint address="net.tcp://localhost:8081" binding="netTcpBinding" bindingConfiguration="NewBinding0" contract="Learn.Library.WCF.IService"> </endpoint> </service> </services> </system.serviceModel> </configuration>
代码版1. 服务器 ServiceHost host = new ServiceHost(typeof(MyService), new Uri("net.tcp://localhost:8081")); NetTcpBinding binding = new NetTcpBinding(); binding.Security.Mode = SecurityMode.Transport; binding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign; binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate; host.AddServiceEndpoint(typeof(IService), binding, ""); host.Credentials.ServiceCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "MyServer"); host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None; host.Open();
2. 客户端1 using (ServiceClient client = new ServiceClient()) { client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "Client1"); client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None; Console.WriteLine(client.Test()); }
app.config <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <netTcpBinding> <binding name="NetTcpBinding_IService"> <security mode="Transport"> <transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" /> <message clientCredentialType="Windows" /> </security> </binding> </netTcpBinding> </bindings> <client> <endpoint address="net.tcp://localhost:8081/" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IService" contract="ConsoleApplication1.localhost.IService" name="NetTcpBinding_IService"> <identity> <dns value="MyServer" /> </identity> </endpoint> </client> </system.serviceModel> </configuration>
3. 客户端2 NetTcpBinding binding2 = new NetTcpBinding(); binding2.Security.Mode = SecurityMode.Transport; binding2.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign; binding2.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate; EndpointAddress endpoint = new EndpointAddress(new Uri("net.tcp://localhost:8081"), EndpointIdentity.CreateDnsIdentity("MyServer")); ChannelFactory<IService> factory = new ChannelFactory<IService>(binding2, endpoint); factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "Client1"); factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None; IService client = factory.CreateChannel(); using (client as IDisposable) { Console.WriteLine(client.Test()); }
转载地址:https://blog.csdn.net/zengjibing/article/details/3814221 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月17日 10时19分11秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
交换变量
2019-04-29
考拉兹猜想
2019-04-29
利息计算
2019-04-29
排列的个数
2019-04-29
开平方
2019-04-29
C语言atoi() 函数用来将字符串转换成整数(int)
2019-04-29
C语言atol()函数:将字符串转换成long(长整型)
2019-04-29
C语言atof()函数:将字符串转换为double(双精度浮点数)
2019-04-29
角谷步数
2019-04-29
C语言二级模拟系统
2019-04-29
乘法算式
2019-04-29
信用卡号校验
2019-04-29
立方和等式
2019-04-29
字符串压缩
2019-04-29
大数相加
2019-04-29
随机投点——用蒙特卡洛方法求π的近似值
2019-04-29
实验一 winrunner的安装使用
2019-04-29
Problem 1001 有多少个整点
2019-04-29
Problem 1002 Another A+B Problem
2019-04-29
Problem 1004 成绩与等级
2019-04-29