WCF每个连接服务器证书验证

时间:2013-12-06 19:11:35

标签: c# wcf ssl

我正在尝试将https证书验证仅绕过我们自己的测试环境(多台计算机),同时尝试为所有其他连接保留证书验证。

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

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

但是,这是一个全局设置,我想仅将其应用于特定连接。这甚至是可能/支持的使用场景吗?

7 个答案:

答案 0 :(得分:9)

使用.net 4.5时,我终于找到了真正的解决方案。

此代码允许您仅为特定WCF客户端使用自定义验证程序。

已使用BasicHttpSecurityMode.Transport对BasicHttpBinding进行了测试。

ClientBase.ClientCredentials.ServiceCertificate中有一个名为SslCertificateAuthentication的新媒体资源。

您可以使用X509ServiceCertificateAuthentication初始化此属性,您可以在其中提供自定义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");
        }
    }
}

答案 1 :(得分:3)

似乎在.NET 4.5中,您可以执行以下操作:

var request = (HttpWebRequest)WebRequest.Create(url);
request.ServerCertificateValidationCallback += 
    (sender, certificate, chain, sslPolicyErrors) => true

我最初没有意识到这一点,因为您实际上必须将Create方法的结果转换为HttpWebRequest,因为抽象WebRequest不包含此委托。

答案 2 :(得分:2)

这样的事情:

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;
}

请注意sender参数上的documentation

  传递给RemoteCertificateValidationCallback的

sender参数可以是主机字符串名称,也可以是从WebRequest派生的对象(例如,HttpWebRequest),具体取决于CertificatePolicy属性

免责声明 - 我没有对此进行测试,我是根据文档编写的。 YMMV。

答案 3 :(得分:1)

我想建议你采用更“犹太”的方式(从信息安全的角度来看):

  1. Create您的开发者计算机的自签名唯一证书
  2. Add此证书到您的测试服务实例上的“受信任的根”证书存储
  3. 将证书添加到应用程序允许的列表(如果存在)
  4. 这将允许您在不在代码中创建“后门”的情况下使用您的服务。这也允许您限制对测试环境的测试访问,同时在Test和Prod实例上具有相同的代码。

答案 4 :(得分:1)

您实际上可以使用以下代码禁用每个客户端/渠道的SSL证书验证:

var noCertValidationAuth = new X509ServiceCertificateAuthentication() 
{ 
    CertificateValidationMode = X509CertificateValidationMode.None 
};
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = noCertValidationAuth;

这个帖子实际上是answer的变体,所以在那里赞不绝口。

答案 5 :(得分:0)

您可以做的是在您的web.config文件中放置一个设置。

然后在您的代码中检查web.config文件中的值。然后根据该值设置证书验证。

修改

一个选项是:

String url = "https://www.stackoverflow.com";
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };

另一个是:http://weblog.west-wind.com/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors

修改2

尝试这样的事情:

ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation;


private static bool customXertificateValidation(object sender, X509Certificate cert, 
X509Chain chain, SslPolicyErrors error)
{
    if (check something here)
   {
    return true;
   }
   return false;
}

答案 6 :(得分:0)

我在Web.config文件中使用了一个标志来指示证书何时自签名 我们也知道我们处于开发环境中:

<add key="isSelfSignedCertificate" value="true"/>

在代码中,我们必须检查此标志以应用证书验证例外:

using System.Net;

bool isSelfSignedCertificate = Convert.ToBoolean(ConfigurationManager.AppSettings["isSelfSignedCertificate"]);

if (isSelfSignedCertificate)
{
    ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
}