C# 忽略控制台应用程序中的web浏览器SSL安全警报

C# 忽略控制台应用程序中的web浏览器SSL安全警报,c#,https,browser,certificate,webbrowser-control,C#,Https,Browser,Certificate,Webbrowser Control,我正在创建一个控制台应用程序,可以远程捕获网站的屏幕截图。除了我无法避免证书错误之外,一切都正常。每次我收到我无法通过的弹出消息 我尝试使用: ServicePointManager.ServerCertificateValidationCallback=新的RemoteCertificateValidationCallback(ValidateServerCertificate) 但它不起作用。 还尝试了以下解决方案: 但它似乎不适用于从控制台应用程序调用的webbrowser 有什么想法吗?

我正在创建一个控制台应用程序,可以远程捕获网站的屏幕截图。除了我无法避免证书错误之外,一切都正常。每次我收到我无法通过的弹出消息

我尝试使用:

ServicePointManager.ServerCertificateValidationCallback=新的RemoteCertificateValidationCallback(ValidateServerCertificate)

但它不起作用。 还尝试了以下解决方案: 但它似乎不适用于从控制台应用程序调用的webbrowser


有什么想法吗?

webbrowser控件使用WinInet作为其网络堆栈。设置ServerCertificateValidationCallback对WinInet没有影响

要处理证书错误,需要实现IHttpSecurity服务,并根据请求传递给webbrowser。webbrowser通过ActiveX主机上实现的IServiceProvider查询主机服务。假设您使用的是Windows窗体,则需要执行以下操作:

  • 从WebBrowser派生一个类
  • 创建从WebBrowser.WebBrowserSite派生的嵌套类(从嵌套类派生的唯一方法)
  • 覆盖CreateWebBrowserSiteBase并返回webbrowser站点的新实例
  • 在webbrowser站点上实施IServiceProvider
  • 实现IServiceProvider.QueryService,以便在请求IHttpSecurity服务时返回IHttpSecurity IMeplementation
  • 处理IHttpSecurity.on安全性问题并返回S\u OK
  • 在表单中使用新的webbrowser
示例代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void webBrowser1_DocumentCompleted(object sender, 
        WebBrowserDocumentCompletedEventArgs e)
    {
        if (e.Url.ToString() == "about:blank")
        {
            //create a certificate mismatch
            webBrowser1.Navigate("https://74.125.225.229");
        }
    }
}
[Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface UCOMIServiceProvider
{
    [return: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    int QueryService(
        [In] ref Guid guidService,
        [In] ref Guid riid,
        [Out] out IntPtr ppvObject);
}
[ComImport()]
[ComVisible(true)]
[Guid("79eac9d5-bafa-11ce-8c82-00aa004ba90b")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IWindowForBindingUI
{ 
    [return: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    int GetWindow(
        [In] ref Guid rguidReason,
        [In, Out] ref IntPtr phwnd);
}

[ComImport()]
[ComVisible(true)]
[Guid("79eac9d7-bafa-11ce-8c82-00aa004ba90b")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IHttpSecurity
{
    //derived from IWindowForBindingUI
    [return: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    int GetWindow(
        [In] ref Guid rguidReason,
        [In, Out] ref IntPtr phwnd);
    [PreserveSig]
    int OnSecurityProblem(
        [In, MarshalAs(UnmanagedType.U4)] uint dwProblem);
}
public class MyWebBrowser : WebBrowser
{
    public static Guid IID_IHttpSecurity 
        = new Guid("79eac9d7-bafa-11ce-8c82-00aa004ba90b");
    public static Guid IID_IWindowForBindingUI 
        = new Guid("79eac9d5-bafa-11ce-8c82-00aa004ba90b");        
    public const int S_OK = 0;
    public const int S_FALSE = 1;
    public const int E_NOINTERFACE = unchecked((int)0x80004002);
    public const int RPC_E_RETRY = unchecked((int)0x80010109);
    protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
    {
        return new MyWebBrowserSite(this);
    }
    class MyWebBrowserSite : WebBrowserSite, 
        UCOMIServiceProvider, 
        IHttpSecurity, 
        IWindowForBindingUI 
    {
        private MyWebBrowser myWebBrowser;
        public MyWebBrowserSite(MyWebBrowser myWebBrowser)
            :base(myWebBrowser)
        {
            this.myWebBrowser = myWebBrowser;
        }
        public int QueryService(ref Guid guidService
            , ref Guid riid
            , out IntPtr ppvObject)
        {
            if (riid ==IID_IHttpSecurity)
            {
                ppvObject= Marshal.GetComInterfaceForObject(this
                    , typeof(IHttpSecurity));
                return S_OK;
            }
            if (riid == IID_IWindowForBindingUI)
            {
                ppvObject = Marshal.GetComInterfaceForObject(this
                    , typeof(IWindowForBindingUI));
                return S_OK;
            }
            ppvObject = IntPtr.Zero;
            return E_NOINTERFACE;
        }

        public int GetWindow(ref Guid rguidReason
            , ref IntPtr phwnd)
        {
            if (rguidReason == IID_IHttpSecurity 
                || rguidReason == IID_IWindowForBindingUI)
            {
                phwnd = myWebBrowser.Handle;
                return S_OK;
            }
            else
            {
                phwnd = IntPtr.Zero;
                return S_FALSE;
            }
        }

        public int OnSecurityProblem(uint dwProblem)
        {
            //ignore errors
            //undocumented return code, does not work on IE6
            return S_OK;
        }
    }
}

终于找到了答案。

我一直在尝试绕过作为控制台应用程序运行的无头IE浏览器的SSL证书错误(

提供了大部分答案,但我仍然无法使用
Application.Run()
,因为它会锁定主线程上的执行,并且我需要执行循环中的其他事件,另外,用消息泵实例化
ApplicationContext
似乎太复杂了

我得到的答案非常简单。只需创建一个循环并运行
Application.DoEvents()

下面是一些工作代码。我对它进行了简化,以适应这里发布的问题

请确保:

  • 您正在作为控制台应用程序项目运行
  • 将项目引用添加到
    System.Windows.Forms
  • 希望有帮助

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace IgnoreSSLErrorBrowserConsoleApp
    {
        public class Program
        {
            [STAThread]
            public static void Main(string[] args)
            {
                MyWebBrowser browser = new MyWebBrowser();
                browser.Navigate("about:blank");
                browser.DocumentCompleted += delegate (object obj, WebBrowserDocumentCompletedEventArgs e) {
                    if (e.Url.ToString() == "about:blank") {
                        // This is the SSL path where certificate error occurs
                        browser.Navigate("https://localhost");
                    }
                };
                while (browser.ReadyState != WebBrowserReadyState.Complete) {
                    Application.DoEvents();
                    // RunOtherEvents();
                }
    
            }
        }
    
        [Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [ComImport]
        public interface UCOMIServiceProvider
        {
            [return: MarshalAs(UnmanagedType.I4)]
            [PreserveSig]
            int QueryService(
                [In] ref Guid guidService,
                [In] ref Guid riid,
                [Out] out IntPtr ppvObject);
        }
        [ComImport()]
        [ComVisible(true)]
        [Guid("79eac9d5-bafa-11ce-8c82-00aa004ba90b")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IWindowForBindingUI
        {
            [return: MarshalAs(UnmanagedType.I4)]
            [PreserveSig]
            int GetWindow(
                [In] ref Guid rguidReason,
                [In, Out] ref IntPtr phwnd);
        }
    
        [ComImport()]
        [ComVisible(true)]
        [Guid("79eac9d7-bafa-11ce-8c82-00aa004ba90b")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IHttpSecurity
        {
            //derived from IWindowForBindingUI
            [return: MarshalAs(UnmanagedType.I4)]
            [PreserveSig]
            int GetWindow(
                [In] ref Guid rguidReason,
                [In, Out] ref IntPtr phwnd);
            [PreserveSig]
            int OnSecurityProblem(
                [In, MarshalAs(UnmanagedType.U4)] uint dwProblem);
        }
        public class MyWebBrowser : WebBrowser
        {
            public static Guid IID_IHttpSecurity
                = new Guid("79eac9d7-bafa-11ce-8c82-00aa004ba90b");
            public static Guid IID_IWindowForBindingUI
                = new Guid("79eac9d5-bafa-11ce-8c82-00aa004ba90b");
            public const int S_OK = 0;
            public const int S_FALSE = 1;
            public const int E_NOINTERFACE = unchecked((int)0x80004002);
            public const int RPC_E_RETRY = unchecked((int)0x80010109);
            protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
            {
                return new MyWebBrowserSite(this);
            }
            class MyWebBrowserSite : WebBrowserSite,
                UCOMIServiceProvider,
                IHttpSecurity,
                IWindowForBindingUI
            {
                private MyWebBrowser myWebBrowser;
                public MyWebBrowserSite(MyWebBrowser myWebBrowser)
                    : base(myWebBrowser)
                {
                    this.myWebBrowser = myWebBrowser;
                }
                public int QueryService(ref Guid guidService
                    , ref Guid riid
                    , out IntPtr ppvObject)
                {
                    if (riid == IID_IHttpSecurity)
                    {
                        ppvObject = Marshal.GetComInterfaceForObject(this
                            , typeof(IHttpSecurity));
                        return S_OK;
                    }
                    if (riid == IID_IWindowForBindingUI)
                    {
                        ppvObject = Marshal.GetComInterfaceForObject(this
                            , typeof(IWindowForBindingUI));
                        return S_OK;
                    }
                    ppvObject = IntPtr.Zero;
                    return E_NOINTERFACE;
                }
    
                public int GetWindow(ref Guid rguidReason
                    , ref IntPtr phwnd)
                {
                    if (rguidReason == IID_IHttpSecurity
                        || rguidReason == IID_IWindowForBindingUI)
                    {
                        phwnd = myWebBrowser.Handle;
                        return S_OK;
                    }
                    else
                    {
                        phwnd = IntPtr.Zero;
                        return S_FALSE;
                    }
                }
    
                public int OnSecurityProblem(uint dwProblem)
                {
                    //ignore errors
                    //undocumented return code, does not work on IE6
                    return S_OK;
                }
            }
        }
    }
    

    委托“ValidateServerCertificate”必须返回true。它在您的环境中返回什么?它确实返回true,但不起作用。您能提供更多的源代码吗?特别是您用来与Web服务器通信的对象。Web部分非常简单,它是这样的:WebBrowser wb=new WebBrowser();wb.导航(“地址”,错误);在此之后,我得到了带有证书警报的弹出窗口。不幸的是,WebBrowser控件似乎不支持使用ServicePointManager。感谢您的回答。我已经尝试过类似的解决方案,但有一个问题。只要webbrowser嵌入到您的示例中的表单中,它就工作得很好。问题是,如果您将webbrowser作为表单的对象调用,它不会处理弹出窗口。webbrowser Activex是单线程组件,因此需要消息泵。运行消息泵的一种简单方法是切换到windows窗体程序并调用Application.run(窗体还负责处理控件)。如果您想将消息泵添加到控制台,请检查我知道有使用表单程序的解决方案,但问题是它作为控制台应用程序非常重要泵送消息非常重要,没有它,您不应该期望任何STA COM对象运行。无论你是在控制台还是在表单应用程序中都不重要。对不起,不重要。我认为控制台应用程序中的GUI组件只是要求做更多的工作。为什么选择控制台应用程序?您可以调用AllocateConsole在winforms应用程序中创建控制台,只需通知您即可。