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

标签 c# https browser certificate webbrowser-control

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

我尝试使用:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);

但它不起作用。 还尝试了此处找到的解决方案: http://www.codeproject.com/Articles/31163/Suppressing-Hosted-WebBrowser-Control-Dialogs 但它似乎不适用于从控制台应用程序调用的网络浏览器。

有什么想法吗?

最佳答案

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

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

  • 从 WebBrowser 派生一个类
  • 创建一个从 WebBrowser.WebBrowserSite 派生的嵌套类(您可以从嵌套类派生的唯一方法)
  • 覆盖 CreateWebBrowserSiteBase 并返回您的网络浏览器站点的新实例。
  • 在网络浏览器站点上实现 IServiceProvider
  • 实现 IServiceProvider.QueryService,以便在请求 IHttpSecurity 服务时返回 IHttpSecurity 执行
  • 处理 IHttpSecurity.OnSecurityProblem 并返回 S_OK
  • 在表单中使用新的网络浏览器

示例代码:

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

关于c# - 忽略控制台应用程序中的 Web 浏览器 SSL 安全警报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17698002/

相关文章:

performance - 为什么 Chrome 审核建议我最小化 cookie 大小?

c# - 通过窗口句柄查找进程ID

javascript - 使用 expressjs 3 强制 SSL

apache - 如何避免浏览器在发送响应后呈现恶意内容

html - 从 Blackberry 上的 BrowserField 获取图形对象或位图

php - 火狐浏览器不删除cookies

c# - 创建新数据库还是使用现有的 ASP.NET Identity 数据库?

c# - 使用区域性信息将逗号十进制值转换为点十进制值的最佳方法

c# - 构造函数初始化优化?

ssl - 关于HTTPS的困惑 --> SSL握手是怎么发生的