C# WCF传输安全,匿名访问的消息加密
我正在尝试设置一个WCF客户端,以便与服务对话。连接需要是https(传输安全),我们需要使用公钥进行消息加密。我们没有要显示的客户端证书C# WCF传输安全,匿名访问的消息加密,c#,asp.net,wcf,C#,Asp.net,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.
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;
其中,certificate是仅具有公钥的X509Certificate2对象
当我这样做时,它不会加密消息。使用Fiddler,我看到消息的原始文本通过网络传输,服务给出了一个错误,因为它需要加密消息
编辑:添加了关于TransportWithMessageCrediential的评论这就是我们解决这个问题的方法。我们正在使用CustomBinding进行设置 这将设置绑定
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;
}
}
通常,对大多数人来说,数据加密一次就足够了。你真的想要TLS和消息安全吗?是的,因为它保护了中间人的攻击。我们正在发送PII,并且需要对消息进行加密。对于WSHttpBinding,我认为您只能将安全性设置为
Transport
或message
。你不能两者兼得。您似乎还混淆了加密和凭据。凭据不会加密邮件。他们告诉服务器呼叫者是谁。至于Fiddler能够看到您的消息,您是否让它安装了可信证书?因为如果你这样做,那么它可以做一个中间人的“攻击”。为了防止出现这种情况,可以执行“证书固定”,即检查服务器的证书是否符合预期。WSHttpBinding允许这两种方法()。小提琴确实安装了根CA证书,它允许我解密和查看HTTPS消息,但它仍然显示给我,如果它被加密使用消息加密(因此两者都需要)。“是的,因为它防止中间人攻击”。TLS也应该能够做到这一点,因为它需要一个客户端必须信任的证书。中间人只有在客户信任“中间人”证书的情况下才会成功。只有在有权访问客户证书存储的某些组织进行https检查时,才会发生这种情况。