带有证书的程序化WCF消息安全性 [英] Programmatic WCF Message Security with Certificates
问题描述
我已经使用WSHttpBindings编写了一个自托管的WCF服务,并且正在尝试使用自己生成的证书来实现消息级安全性.不幸的是,我收到了一个隐藏的异常(通过Service Trace Viewer),指出无法识别提供给程序包的凭据."
I've written a self-hosted WCF service using WSHttpBindings and I'm trying to implement message-level security using certificates I've generated myself. Unfortunately I'm getting a buried exception (via the Service Trace Viewer) stating "The credentials supplied to the package were not recognized."
一些注意事项:
- This has to be done in code, not in configuration
- (Server/Client)Cert are certificates that are in the local machine store with accessible private keys to my user while debugging.
- I've googled the hell out of this and found a good resource for setting up WCF message based security here
我不确定我缺少什么.除了创建端点标识之外,大多数这些东西似乎都是直截了当的.无论我使用DnsEndpointIdentities,基于证书的身份还是根本不使用任何身份,都会失败,并显示相同的消息.
I'm not sure what I'm missing. Most of this stuff seems straight forward except for creating the endpoint identities. It fails with the same message whether I use DnsEndpointIdentities, cert based ones, or no identities at all.
有人能指出我正确的方向吗?
Can anyone point me in the right direction?
服务器端:
var binding = new WSHttpBinding
{
Security =
{
Mode = SecurityMode.Message,
Message =
{
ClientCredentialType = MessageCredentialType.Certificate,
AlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256Rsa15
}
}
};
_host = new ServiceHost(this)
{
Credentials =
{
ServiceCertificate =
{
Certificate = ServiceCert
},
ClientCertificate =
{
Certificate = ClientCert,
Authentication =
{
TrustedStoreLocation = StoreLocation.LocalMachine,
RevocationMode = X509RevocationMode.NoCheck,
CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust
}
}
}
};
var address = new Uri(string.Format(@"http://serviceaddress"));
var ep = _host.AddServiceEndpoint(typeof (IService), binding, address);
ep.Address = new EndpointAddress(address, EndpointIdentity.CreateX509CertificateIdentity(ServiceCert));
_host.Open();
客户端:
var binding = new WSHttpBinding
{
Security =
{
Mode = SecurityMode.Message,
Message =
{
ClientCredentialType = MessageCredentialType.Certificate,
AlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256Rsa15
}
}
};
var address = new Uri(@"http://serviceaddress");
var endpoint = new EndpointAddress(address, EndpointIdentity.CreateX509CertificateIdentity(ServerCert));
var channelFactory = new ChannelFactory<IService>(binding, endpoint)
{
Credentials =
{
ServiceCertificate =
{
DefaultCertificate = ServerCert,
Authentication =
{
RevocationMode = X509RevocationMode.NoCheck,
TrustedStoreLocation = StoreLocation.LocalMachine,
CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust
}
},
ClientCertificate =
{
Certificate = ClientCert
}
}
};
var channel = channelFactory.CreateChannel();
推荐答案
此msdn文章帮助很大.我认为问题的根源在于将以下消息安全性参数设置为false:
this msdn article helped tremendously. I think the root of the problem was setting the following message security parameters to false:
httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;
所以现在服务器端的整体代码看起来更像:
So now the overall code for the server side looks more like:
var httpBinding = new WSHttpBinding(SecurityMode.Message);
httpBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;
var httpUri = new Uri("http://serviceaddress");
_host = new ServiceHost(this, httpUri);
_host.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, serverThumbprint);
_host.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
_host.Credentials.ClientCertificate.Authentication.TrustedStoreLocation = StoreLocation.LocalMachine;
_host.AddServiceEndpoint(typeof(IMetaService), httpBinding, httpUri);
_host.Open();
和客户端:
var httpBinding = new WSHttpBinding(SecurityMode.Message);
httpBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;
var httpUri = new Uri("http://serviceaddress");
var httpEndpoint = new EndpointAddress(httpUri, EndpointIdentity.CreateDnsIdentity("name of server cert"));
var newFactory = new ChannelFactory<IMetaService>(httpBinding, httpEndpoint);
newFactory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, "client certificate thumbprint");
newFactory.Credentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, "server certificate thumbprint");
var channel = newFactory.CreateChannel();
这篇关于带有证书的程序化WCF消息安全性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!