Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WCF每连接服务器证书验证_C#_Wcf_Ssl - Fatal编程技术网

C# WCF每连接服务器证书验证

C# WCF每连接服务器证书验证,c#,wcf,ssl,C#,Wcf,Ssl,我试图绕过https证书验证,只对我们自己的测试环境(多台机器)进行验证,同时尝试对所有其他连接进行证书验证 通过在线阅读,大多数(如果不是全部的话)WCF相关的建议似乎指向以下类似的东西 ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 但是,这是一个全局设置,我只想将其应用于特定连接。这是可能的/受支持的使用场景吗?您可以在web.config文件中放置一个设置 然后在代

我试图绕过https证书验证,只对我们自己的测试环境(多台机器)进行验证,同时尝试对所有其他连接进行证书验证

通过在线阅读,大多数(如果不是全部的话)WCF相关的建议似乎指向以下类似的东西

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服务不起作用。有什么想法吗?谢谢你的建议,我们知道这种方法。虽然这是可行的,但这将要求我们在每台需要进行测试连接的机器上重新部署证书,因此这不是我们真正想要的。下面我的答案受到了启发