ssl时如何忽略证书检查

Posted

技术标签:

【中文标题】ssl时如何忽略证书检查【英文标题】:How to ignore the certificate check when ssl 【发布时间】:2012-09-12 11:05:40 【问题描述】:

我正在尝试找到一种在请求 Https 资源时忽略证书检查的方法,到目前为止,我在互联网上找到了一些有用的文章。

但我还是有一些问题。请查看我的代码。我只是不明白代码ServicePointManager.ServerCertificateValidationCallback 是什么意思。

什么时候调用这个委托方法?还有一个问题,我应该在哪个地方写这段代码?在ServicePointManager.ServerCertificateValidationCallback 之前执行还是在Stream stream = request.GetRequestStream() 之前执行?

public HttpWebRequest GetRequest()

    CookieContainer cookieContainer = new CookieContainer();

    // Create a request to the server
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_remoteUrl);

    #region Set request parameters

    request.Method = _context.Request.HttpMethod;
    request.UserAgent = _context.Request.UserAgent;
    request.KeepAlive = true;
    request.CookieContainer = cookieContainer;
    request.PreAuthenticate = true;
    request.AllowAutoRedirect = false;

    #endregion

    // For POST, write the post data extracted from the incoming request
    if (request.Method == "POST")
    
        Stream clientStream = _context.Request.InputStream;
        request.ContentType = _context.Request.ContentType;
        request.ContentLength = clientStream.Length;

        ServicePointManager.ServerCertificateValidationCallback = delegate(
            Object obj, X509Certificate certificate, X509Chain chain, 
            SslPolicyErrors errors)
            
                return (true);
            ;

            Stream stream = request.GetRequestStream();

            ....
        

        ....

        return request;
    
   

【问题讨论】:

C# Ignore certificate errors?的可能重复 【参考方案1】:

在 .NetCore 3.1 上,您可以通过声明自定义验证方法来解决此问题。

ServicePointManager.ServerCertificateValidationCallback = delegate  return true; ;  
  

所以在发出请求之前,声明这个回调方法

ServicePointManager.ServerCertificateValidationCallback = delegate  return true; ;    
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://someurl.com/service/");  
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();  
  

这样,验证将始终通过,因为您的自定义方法始终返回 true 值。

【讨论】:

【参考方案2】:

对于 .net 核心

using (var handler = new HttpClientHandler())
 
    // allow the bad certificate
    handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => true;
    using (var httpClient = new HttpClient(handler))
    
        await httpClient.PostAsync("the_url", null);
    

【讨论】:

【参考方案3】:

此解决方案的 Unity C# 版本:

void Awake()

    System.Net.ServicePointManager.ServerCertificateValidationCallback += ValidateCertification;


void OnDestroy()

    ServerCertificateValidationCallback = null;


public static bool ValidateCertification(object sender, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)

    return true;

【讨论】:

赞成这个因为 Unity 会抛出任何 get 或 set of handler.ServerCertificateCustomValidationCallback【参考方案4】:

CA5386:漏洞分析工具会提醒您注意这些代码。

正确代码:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) =>

   return (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != SslPolicyErrors.RemoteCertificateNotAvailable;
;

【讨论】:

【参考方案5】:

明确表达...

ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(CertCheck);

private static bool CertCheck(object sender, X509Certificate cert,
X509Chain chain, System.Net.Security.SslPolicyErrors error)

    return true;

【讨论】:

【参考方案6】:

您可以在 HttpClient 的本地实例上设置回调,而不是向 ServicePointManager 添加一个将全局覆盖证书验证的回调。这种方法应该只影响使用该 HttpClient 实例进行的调用。

这里是示例代码,展示了如何在 Web API 控制器中实现忽略特定服务器的证书验证错误。

using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

public class MyController : ApiController


    // use this HttpClient instance when making calls that need cert errors suppressed
    private static readonly HttpClient httpClient;

    static MyController()
    
        // create a separate handler for use in this controller
        var handler = new HttpClientHandler();

        // add a custom certificate validation callback to the handler
        handler.ServerCertificateCustomValidationCallback = ((sender, cert, chain, errors) => ValidateCert(sender, cert, chain, errors));

        // create an HttpClient that will use the handler
        httpClient = new HttpClient(handler);
    

    protected static ValidateCert(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
    

        // set a list of servers for which cert validation errors will be ignored
        var overrideCerts = new string[]
        
            "myproblemserver",
            "someotherserver",
            "localhost"
        ;

        // if the server is in the override list, then ignore any validation errors
        var serverName = cert.Subject.ToLower();
        if (overrideCerts.Any(overrideName => serverName.Contains(overrideName))) return true;

        // otherwise use the standard validation results
        return errors == SslPolicyErrors.None;
    


【讨论】:

这不是仅适用于 .NET Core 吗? (或者每当将 ServerCertificateCustomValidationCallback 添加到 HttpClientHandler 时)? 这个解决方案应该在 .Net Framework 4.5 及更高版本以及 .Net Core 中工作(虽然我没有在 .Net Core 中测试过)。 @Sheldon,这是一个宝石 :) 在我的 .net 和 .net 核心应用程序之间的 localhost api 调用中成功使用。不错的解决方法,不接受所有。【参考方案7】:

上面的几个答案有效。我想要一种方法,我不必不断地更改代码,也不会使我的代码不安全。因此,我创建了一个白名单。白名单可以在任何数据存储中维护。我使用了配置文件,因为它是一个非常小的列表。

我的代码如下。

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => 
    return error == System.Net.Security.SslPolicyErrors.None || certificateWhitelist.Contains(cert.GetCertHashString());
;

【讨论】:

【参考方案8】:

顺便说一句,这是我所知道的在给定应用程序中关闭所有证书验证的最简单的方法:

ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;

【讨论】:

【参考方案9】:

提示:您还可以使用此方法来跟踪即将到期的证书。如果您发现即将过期的证书并且可以及时修复它,这可以节省您的培根。对第三方公司也有好处 - 对我们来说,这是 DHL / FedEx。 DHL 只是让证书过期,这让我们在感恩节前 3 天搞砸了。幸运的是,我正在修复它……这一次!

    private static DateTime? _nextCertWarning;
    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
    
        if (error == SslPolicyErrors.None)
        
            var cert2 = cert as X509Certificate2;
            if (cert2 != null)
             
                // If cert expires within 2 days send an alert every 2 hours
                if (cert2.NotAfter.AddDays(-2) < DateTime.Now)
                
                    if (_nextCertWarning == null || _nextCertWarning < DateTime.Now)
                    
                        _nextCertWarning = DateTime.Now.AddHours(2);

                        ProwlUtil.StepReached("CERT EXPIRING WITHIN 2 DAYS " + cert, cert.GetCertHashString());   // this is my own function
                    
                
            

            return true;
        
        else
        
            switch (cert.GetCertHashString())
            
                // Machine certs - SELF SIGNED
                case "066CF9CAD814DE2097D367F22D3A7E398B87C4D6":    

                    return true;

                default:
                    ProwlUtil.StepReached("UNTRUSTED CERT " + cert, cert.GetCertHashString());
                    return false;
            
        
    

【讨论】:

确保处理您的警报机制可能具有过期证书的情况 - 否则您最终会遇到 ***! ProwlUtil.StepReached 是什么? 抱歉,这只是我自己调用 Prowl API 的方法,它可以向我的手机发送通知。但是你想记录它是好的。我喜欢因为这样的事情被我的手机窃听!【参考方案10】:

对于有兴趣在每个请求的基础上应用此解决方案的任何人,这是一个选项并使用 Lambda 表达式。同样的 Lambda 表达式也可以应用于 blak3r 提到的全局过滤器。此方法似乎需要 .NET 4.5。

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

在 .NET 4.0 中,Lambda 表达式可以应用于全局过滤器

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

【讨论】:

是否有针对 FtpWebRequest 的按请求解决方案? 在我的 4.0 中似乎存在良好 我认为这是迄今为止对“全局”变体更好的解决方案,尽管我当然可以理解您为什么想要它。我个人喜欢一个请求工厂,然后管理这个验证回调。谢谢亚当,很好的解决方案。 返回true 是您在开发过程中进行试验时可以做的事情,但它是不安全的。它应该是有条件的。 使用(HttpWebRequest)WebRequest.Create(url) 是完全有效的,但在我的盒子里,HttpWebRequest.Create(url) 仍然存在于针对.Net 4.6.2 的项目中。 Chef 的选择,但此时 HttpClient 可能是更好的 API。【参考方案11】:

还有短委托解决方案:

ServicePointManager.ServerCertificateValidationCallback = delegate  return true; ; 

【讨论】:

总是返回 true 是不安全的。 是的,始终信任所有 SSL 证书是不安全的定义。尽可能避免这样做。 @AndrejRommel 你的推荐方式是什么? 推荐的方法是创建一个有效的 SSL 证书并在您可以控制服务器的情况下正确使用它。我们最终使用letsencrypt.org创建了一个。 @AndrejRommel 很有趣,我用 HttpWebRequest 得到了这个,它突然抛出与此相关的异常,但证书很好,我希望更多文章解释 HttpWebRequest 验证其他人的背后机制不是,但一切都只是说要关闭它,我知道这是错误的!【参考方案12】:

根据 Adam 的回答和 Rob 的评论,我使用了这个:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => certificate.Issuer == "CN=localhost";

它在某种程度上过滤了“忽略”。当然可以根据需要添加其他发行人。 这是在 .NET 2.0 中测试的,因为我们需要支持一些遗留代码。

【讨论】:

@karank 抱歉回复晚了 - 它可以在实际通话之前添加到任何地方,例如。在调用 request.GetResponse() 之前。请注意,在您的情况下,Issuer 可能包含其他内容。【参考方案13】:

已经提到,在 .NET 4.5 之前,请求访问其ServicePointManager 的属性不可用。

这是 .NET 4.0 代码,可让您根据每个请求访问 ServicePoint。它不会让您访问每个请求的回调,但它应该让您找到有关问题的更多详细信息。只需访问scvPoint.Certificate(或ClientCertificate,如果您愿意)属性。

WebRequest request = WebRequest.Create(uri);

// oddity: these two .Address values are not necessarily the same!
//  The service point appears to be related to the .Host, not the Uri itself.
//  So, check the .Host vlaues before fussing in the debugger.
//
ServicePoint svcPoint = ServicePointManager.FindServicePoint(uri);
if (null != svcPoint)

    if (!request.RequestUri.Host.Equals(svcPoint.Address.Host, StringComparison.OrdinalIgnoreCase))
    
        Debug.WriteLine(".Address              == " + request.RequestUri.ToString());
        Debug.WriteLine(".ServicePoint.Address == " + svcPoint.Address.ToString());
    
    Debug.WriteLine(".IssuerName           == " + svcPoint.Certificate.GetIssuerName());

【讨论】:

同意!但是,这个 OP 是关于如何ignore 他们,而不是信任他们。 无论如何,使用 ServicePoint不能 总是信任所有 SSL 证书,都不忽略所有证书,因为没有ServerCertificateValidationCallbackServicePoint 中的委托【参考方案14】:

除了 Sani 和 blak3r 的答案之外,我还在我的应用程序的启动代码中添加了以下内容,但在 VB 中:

'** Overriding the certificate validation check.
Net.ServicePointManager.ServerCertificateValidationCallback = Function(sender, certificate, chain, sslPolicyErrors) True

似乎可以解决问题。

【讨论】:

【参考方案15】:

这对我有用:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                        System.Security.Cryptography.X509Certificates.X509Chain chain,
                        System.Net.Security.SslPolicyErrors sslPolicyErrors)
    
        return true; // **** Always accept
    ;

来自这里的片段:http://www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors

【讨论】:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; 总是返回 true 是不安全的。它应该有条件地返回 true。 这是每个进程的,所以不安全。【参考方案16】:

由于只有一个全局ServicePointManager,设置ServicePointManager.ServerCertificateValidationCallback 将产生所有后续请求都将继承此策略的结果。因为它是一个全局“设置”,所以最好在Global.asax 的Application_Start 方法中设置它。

设置回调会覆盖默认行为,您可以自己创建自定义验证例程。

【讨论】:

对于没有 Global.asax 的客户怎么办?我正在从手持设备调用在本地网络上运行的 REST 服务。 这个问题是针对HttpWebRequest的。如果您使用任何其他方式,则必须查看文档如何完成此操作。 我正在使用WebRequest,它被强制转换为HttpWebRequest,例如:((HttpWebRequest)request).Accept = contentType; 如我的回答中所述:最好在 Global.asax 中设置它,而不是要求。您甚至可以在调用 REST 服务之前设置它。 请参阅this link 了解可能的解决方案。

以上是关于ssl时如何忽略证书检查的主要内容,如果未能解决你的问题,请参考以下文章

如何让 ruby​​ 的 xmlrpc 客户端忽略 SSL 证书错误?

如何使用 QWebEngineView 忽略 SSL 证书错误

如何忽略 SSL 证书 Java

如何忽略 Newman 中的 SSL 证书错误

让git忽略SSL证书错误。及push项目时消除警告

如何让easy_install忽略证书