C# WCF每连接服务器证书验证
我试图绕过https证书验证,只对我们自己的测试环境(多台机器)进行验证,同时尝试对所有其他连接进行证书验证 通过在线阅读,大多数(如果不是全部的话)WCF相关的建议似乎指向以下类似的东西C# WCF每连接服务器证书验证,c#,wcf,ssl,C#,Wcf,Ssl,我试图绕过https证书验证,只对我们自己的测试环境(多台机器)进行验证,同时尝试对所有其他连接进行证书验证 通过在线阅读,大多数(如果不是全部的话)WCF相关的建议似乎指向以下类似的东西 ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 但是,这是一个全局设置,我只想将其应用于特定连接。这是可能的/受支持的使用场景吗?您可以在web.config文件中放置一个设置 然后在代
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
但是,这是一个全局设置,我只想将其应用于特定连接。这是可能的/受支持的使用场景吗?您可以在web.config文件中放置一个设置 然后在代码中检查web.config文件中的值。然后根据该值设置证书验证 编辑 一种选择是:
String url = "https://www.stackoverflow.com";
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };
另一个是:
编辑2
试着这样做:
ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation;
private static bool customXertificateValidation(object sender, X509Certificate cert,
X509Chain chain, SslPolicyErrors error)
{
if (check something here)
{
return true;
}
return false;
}
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidateCert);
public static bool ValidateCert(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
string requestHost;
if(sender is string)
{
requestHost = sender.ToString();
}
else
{
HttpWebRequest request = sender as HttpWebRequest;
if(request != null)
{
requestHost = request.Host;
}
}
if(!string.IsNullOrEmpty(requestHost) && requestHost == "my_test_machine")
return true;
return sslPolicyErrors == SslPolicyErrors.None;
}
大概是这样的:
ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation;
private static bool customXertificateValidation(object sender, X509Certificate cert,
X509Chain chain, SslPolicyErrors error)
{
if (check something here)
{
return true;
}
return false;
}
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidateCert);
public static bool ValidateCert(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
string requestHost;
if(sender is string)
{
requestHost = sender.ToString();
}
else
{
HttpWebRequest request = sender as HttpWebRequest;
if(request != null)
{
requestHost = request.Host;
}
}
if(!string.IsNullOrEmpty(requestHost) && requestHost == "my_test_machine")
return true;
return sslPolicyErrors == SslPolicyErrors.None;
}
请注意发送器
参数上的:
传递给RemoteCertificateValidationCallback的发送方参数可以是主机字符串名称,也可以是从WebRequest派生的对象(例如HttpWebRequest),具体取决于CertificatePolicy属性
免责声明-我没有测试这个,我是根据文档编写的。YMMV.我想向您推荐一种更“洁净”的方式(从信息安全的角度):
这将允许您使用服务,而无需在代码中创建“后门”。这也将允许您仅在测试和产品实例上具有相同代码的情况下限制对测试环境的测试访问。类似于.NET 4.5,您可以执行以下操作:
var request = (HttpWebRequest)WebRequest.Create(url);
request.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => true
我最初没有意识到这一点,因为实际上您必须将
Create
方法的结果转换为HttpWebRequest
,因为抽象WebRequest
不包含此委托 我在Web.config文件中使用了一个标志来指示证书何时自签名
我们也知道,我们正处于一个发展环境中:
<add key="isSelfSignedCertificate" value="true"/>
在使用.NET4.5时,我终于找到了一个真正的解决方案 此代码允许您仅对特定WCF客户端使用自定义验证器 它已经通过
BasicHttpSecurityMode.Transport
针对BasicHttpBinding进行了测试
ClientBase.ClientCredentials.ServiceCertificate
中有一个名为的新属性
您可以使用初始化此属性,其中可以提供自定义的X509CertificateValidator
例如:
// initialize the ssl certificate authentication
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.Custom,
CustomCertificateValidator = new CustomValidator(serverCert)
};
// simple custom validator, only valid against a specific thumbprint
class CustomValidator : X509CertificateValidator
{
private readonly X509Certificate2 knownCertificate;
public CustomValidator(X509Certificate2 knownCertificate)
{
this.knownCertificate = knownCertificate;
}
public override void Validate(X509Certificate2 certificate)
{
if (this.knownCertificate.Thumbprint != certificate.Thumbprint)
{
throw new SecurityTokenValidationException("Unknown certificate");
}
}
}
实际上,您可以使用以下代码禁用每个客户端/通道的SSL证书验证:
var noCertValidationAuth = new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None
};
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = noCertValidationAuth;
它实际上是这个线程中的一个变体,因此值得称赞。好吧,一旦我设置了ServerCertificateValidationCallback,它将影响所有未来的连接,所以我不确定如何通过web.config实现这一点。请提供一个例子。这可能适用于HttpWebRequest,但我正在寻找专门针对WCF的设置。可以通过使用http请求设置特定端点并将deletegates标记为仅用于此端点来实现。我希望可以设置每个连接的设置。我希望避免在全局验证器上检查主机。看起来效率太低了。不过,这就行了,如果在赏金结束时间附近没有更好的答案,我会给分。我不知道每个连接的设置,但也许比我更开明的人会插手。如果只是在测试时,您可以将代码包装为#If DEBUG…因为没有明显的方法可以在每个WCF连接上执行此操作,这是最接近它的方法。遗憾的是,您不能简单地将证书验证应用于单个连接,这将非常有用。但是,这对WSDL服务不起作用。有什么想法吗?谢谢你的建议,我们知道这种方法。虽然这是可行的,但这将要求我们在每台需要进行测试连接的机器上重新部署证书,因此这不是我们真正想要的。下面我的答案受到了启发