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

问题描述 投票:9回答:7

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

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

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

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

c# wcf ssl
7个回答
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;
}

注意documentation参数上的sender

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

免责声明 - 我没有测试这个,我是根据文档编写的。因人而异。


9
投票

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

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

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

SslCertificateAuthentication有一处名为ClientBase.ClientCredentials.ServiceCertificate的新酒店。

您可以使用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");
        }
    }
}

3
投票

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

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

我最初没有意识到,因为你实际上必须将qazxsw poi方法的结果投射到qazxsw poi,因为抽象的qazxsw poi不包含这个委托。


1
投票

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

  1. Create是您的开发人员机器的自签名唯一证书
  2. HttpWebRequest此证书到您的测试服务实例上的“Trusted root”证书存储区
  3. 将证书添加到应用程序的允许列表(如果存在)

这将允许您使用您的服务,而无需在代码中创建“后门”。这也允许您限制对测试环境的测试访问,同时在Test和Prod实例上具有相同的代码。


1
投票

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

WebRequest

它实际上是这个帖子中Create的一个变种,所以在那里赞不绝口。


0
投票

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

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

编辑

一种选择是:

Add

另一个是:var noCertValidationAuth = new X509ServiceCertificateAuthentication() { CertificateValidationMode = X509CertificateValidationMode.None }; client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = noCertValidationAuth;

编辑2

尝试这样的事情:

answer

0
投票

我在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
© www.soinside.com 2019 - 2024. All rights reserved.