以编程方式使用证书身份验证配置 WCF 服务客户端
Posted
技术标签:
【中文标题】以编程方式使用证书身份验证配置 WCF 服务客户端【英文标题】:Configure WCF service client with certificate authentication programmatically 【发布时间】:2012-02-06 17:09:57 【问题描述】:如何在 c# 中以编程方式使用证书身份验证设置 ServiceClient? 而且我不想使用.config。
using(var srv = GetServiceInstance())
srv.DoStuff()
private TheServiceClient GetServiceInstance()
var service = new TheServiceClient(CreateWsHttpBinding(), CreateEndpointAdress());
return service;
private static WSHttpBinding CreateWsHttpBinding()
var wsHttpBinding = new WSHttpBinding();
wsHttpBinding.Security.Mode = SecurityMode.Message;
wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
wsHttpBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
wsHttpBinding.Security.Transport.Realm = "";
wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
wsHttpBinding.Security.Message.NegotiateServiceCredential = true;
wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
wsHttpBinding.Name = "Bindingname";
wsHttpBinding.CloseTimeout = TimeSpan.FromMinutes(1);
wsHttpBinding.OpenTimeout = TimeSpan.FromMinutes(1);
wsHttpBinding.ReceiveTimeout = TimeSpan.FromMinutes(10);
wsHttpBinding.SendTimeout = TimeSpan.FromMinutes(1);
wsHttpBinding.BypassProxyOnLocal = false;
wsHttpBinding.TransactionFlow = false;
wsHttpBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
wsHttpBinding.MaxBufferPoolSize = 524288;
wsHttpBinding.MaxReceivedMessageSize = 65536;
wsHttpBinding.MessageEncoding = WSMessageEncoding.Text;
wsHttpBinding.TextEncoding = Encoding.UTF8;
wsHttpBinding.UseDefaultWebProxy = true;
wsHttpBinding.AllowCookies = false;
wsHttpBinding.ReaderQuotas.MaxDepth = 32;
wsHttpBinding.ReaderQuotas.MaxArrayLength = 16384;
wsHttpBinding.ReaderQuotas.MaxStringContentLength = 8192;
wsHttpBinding.ReaderQuotas.MaxBytesPerRead = 4096;
wsHttpBinding.ReaderQuotas.MaxNameTableCharCount = 16384;
wsHttpBinding.ReliableSession.Ordered = true;
wsHttpBinding.ReliableSession.InactivityTimeout = TimeSpan.FromMinutes(10);
wsHttpBinding.ReliableSession.Enabled = false;
return wsHttpBinding;
private static EndpointAddress CreateEndpointAdress()
var store = new X509Store(StoreName.TrustedPeople, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var cert = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, "CN=Certname", false)[0];
store.Close();
var endpointIdentity = EndpointIdentity.CreateX509CertificateIdentity(cert);
var endpoint = new EndpointAddress(new Uri("ServiceUri"), endpointIdentity);
return endpoint;
这就是我目前所拥有的! 使用它会返回一个错误:
未提供客户端证书。指定客户端证书 在 ClientCredentials 中。
有人有想法吗?温柔点,我是新手!
【问题讨论】:
【参考方案1】:正如在 cmets 中发现的另一个答案,您需要直接设置 service.ClientCredentials.ClientCertificate.Certificate
。
【讨论】:
【参考方案2】:可能需要查看该证书是否对机器帐户可见 - 假设您已调试到以下几点:
var cert = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, "CN=Certname", false)[0];
它说找不到?
【讨论】:
找到并设置了证书。 service.ClientCredentials.ClientCertificate.Certificate 为空 你不是要直接设置service.ClientCredentials.ClientCertificate.Certificate
吗?它被记录为读写,对于其他形式的客户端身份验证,我设置了例如ClientCredentials.UserName.UserName
和 ClientCredentials.UserName.Password
直接在前面。我认为EndpointIdentity
的东西是针对服务端点的,而不是客户端。
这也是我想出来的。当我将service.ClientCredentials.ClientCertificate.Certificate = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, "CN=CertName", false)[0];
放入 GetServiceInstance 方法时,它起作用了。我还需要保留我添加 var endpointIdentity = EndpointIdentity.CreateDnsIdentity("DnsIdentity");
的 EndpointIdentity
@Anton 你的评论很有帮助。如果您将评论作为答案发布,我会将其标记为已回答。【参考方案3】:
我认为您缺少合同描述。在这里,是一个关于如何做到这一点的小例子。如果您还有其他问题,我有完整的工作代码。我会帮你的。
ContractDescription Contract = ContractDescription.GetContract(typeof(IEvalService), typeof(EvalServiceClient));
您必须在打开代理之前使用客户端进行初始化。希望它会奏效。
玩得开心
【讨论】:
以上是关于以编程方式使用证书身份验证配置 WCF 服务客户端的主要内容,如果未能解决你的问题,请参考以下文章
通过 HTTPS 上的客户端证书对 WCF 请求进行身份验证