WCF 传输安全,使用匿名访问进行邮件加密



我正在尝试设置 WCF 客户端以与服务通信。 连接必须是https(传输安全(,我们需要使用公钥进行消息加密。 我们没有要出示的客户端证书。

var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
// This is failing because the private key for client authentication is not being set
// binding.Security.Mode = SecurityMode.TransportWithMessageCrediential;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;

然后设置我正在做的公钥

client.ClientCredentials.ServiceCertificate.DefaultCertificate = certificate;

其中证书是仅包含公钥的 X509Certificate2 对象。

当我这样做时,它不会加密消息。 使用 Fiddler,我看到消息的原始文本通过线路,并且服务给出错误,因为它需要加密消息。

编辑:添加了有关TransportWithMessageCrediential的评论

这就是我们解决这个问题的方式。 我们正在使用自定义绑定来设置这一切。

这将设置绑定

private Binding GetBinding()
{
var binding = new CustomBinding()
// This could be configured per service
MessageVersion messageVersion = MessageVersion.Soap12;
TextMessageEncodingBindingElement messageEncodingElement = new TextMessageEncodingBindingElement(messageVersion, Encoding.UTF8);
binding.Elements.Add(messageEncodingElement)
if (/* Encryption is needed */)
{
SecurityBindingElement securityElement = securityElement = SecurityBindingElement.CreateAnonymousForCertificateBindingElement();
securityElement.DefaultAlgorithmSuite = GetEncryptionAlgorithm(); // This will return which algorithm is desired
securityElement.IncludeTimestamp = false; // This is because our services were returning an error when it was included
binding.Elements.Add(securityElement);
HttpsTransportBindingElement httpsTransportElement = new HttpsTransportBindingElement()
if (/* If Windows Authentication is required */)
httpsTransportElement.AuthenticationScheme = AuthenticationSchemes.Negotiate;
binding.Elements.Add(httpsTransportElement)
return binding;
}

然后使用客户端

// By default WCF will check that the DnsName of the certificate matchs the DNS name of the endpoint we need to override this.
// We did want want to require an appliction to use the same cert that is for SSL as for message encryption
EndpointIdentity endpointIdentity = null;
if (endpoint.EncryptionCertificate != null)
endpointIdentity = EndpointIdentity.CreateDnsIdentity(endpoint.EncryptionCertificate.GetCertificate().GetNameInfo(X509NameType.DnsName, false));
else
endpointIdentity = EndpointIdentity.CreateDnsIdentity(endpoint.Address);

AddressHeader[] header = null;
using (var client = new portTypeClient(binding, new EndpointAddress(new Uri(address), endpointIdentity, header)))
{
if (/* Encryption is needed */)
{
var certificate = LoadX509Certificate();
client.ClientCredentials.ServiceCertificate.DefaultCertificate = certificate;
}
}

最新更新