WCF per connection server certificate validation

前端 未结 7 2855
清歌不尽
清歌不尽 2021-02-20 13:50

I\'m trying to bypass https certificate validation only to our own testing environment (multiple machines), while trying to keep certificate validation for all the other connect

相关标签:
7条回答
  • 2021-02-20 13:57

    Seems like in .NET 4.5 you can do the following:

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

    I did not realize it initially, as you actually have to cast result of Create method to HttpWebRequest, as abstract WebRequest does not contain this delegate.

    0 讨论(0)
  • 2021-02-20 14:01

    You actually can disable SSL cert validation per client/channel with this code:

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

    It is actually a variation of answer in this thread, so kudos there.

    0 讨论(0)
  • 2021-02-20 14:01

    Something like this:

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

    Note the documentation on the sender parameter:

    sender parameter passed to the RemoteCertificateValidationCallback can be a host string name or an object derived from WebRequest (HttpWebRequest, for example) depending on the CertificatePolicy property

    Disclaimer - I didn't test this, I wrote it based on the documentation. YMMV.

    0 讨论(0)
  • 2021-02-20 14:03

    What you could do is place a setting in Your web.config file.

    Then in Your code check the value in the web.config file. Then set the certificate validation depending on that value.

    Edit

    One option is:

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

    Another is: http://weblog.west-wind.com/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors

    Edit 2

    Try something like this:

    ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation;
    
    
    private static bool customXertificateValidation(object sender, X509Certificate cert, 
    X509Chain chain, SslPolicyErrors error)
    {
        if (check something here)
       {
        return true;
       }
       return false;
    }
    
    0 讨论(0)
  • 2021-02-20 14:03

    I was finally able to found a real solution when using .net 4.5.

    This code allows you to use a custom validator only for a specific WCF client.

    It has been tested against BasicHttpBinding with BasicHttpSecurityMode.Transport.

    There is a new property named SslCertificateAuthentication in ClientBase.ClientCredentials.ServiceCertificate.

    You can initialize this property with a X509ServiceCertificateAuthentication where you can provide a custom X509CertificateValidator.

    For example:

    // 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");
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-20 14:12

    I used a flag in the Web.config file to indicate when a certificate is self-signed and we also know that we are in a development environment:

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

    In the code we must check this flag to apply the certificate validation exception:

    using System.Net;
    
    bool isSelfSignedCertificate = Convert.ToBoolean(ConfigurationManager.AppSettings["isSelfSignedCertificate"]);
    
    if (isSelfSignedCertificate)
    {
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
    }
    
    0 讨论(0)
提交回复
热议问题