首页 文章

如何在.NET WebBrowser控件中阻止下载?

提问于
浏览
15

我需要阻止.NET WebBrowser控件显示“您要打开还是保存此文件?”和“另存为”对话框 . 相反,我想显示一个消息框,告诉用户出于安全原因禁用了文件下载 .

我从 WebBrowserFileDownload 事件开始,但它不允许取消 . 然后,我使用CodeProject: Extended .NET 2.0 WebBrowser Control的方法使用接口 DWebBrowserEvents2 基于原始COM调用实现我自己的事件 . 当我根据an MS knowledge base entry about a bug with the FileDownload signature修复代码时,调用了事件处理程序,我可以取消下载 .

但这并不适用于所有下载:指向包含 .exe 的URL的下载URL引发事件并可在对话框出现之前取消 - 但对于其他人(如 .do ),在用户单击 Open 之前不会调用事件处理程序,对话框中的 SaveCancel .

一个可能的解决方案可能是intercept WH_CALLWNDPROCRET messages and 'answer' the dialog before it is shown to the user,但这听起来很费劲,我也更喜欢更清洁的解决方案......

有谁知道如何可靠地阻止所有下载?

3 回答

  • 0

    您可以使用允许取消的 Navigating 事件 .

    在此事件的内部,您可以尝试连接到自己导航的URL,检查http响应标头并在检测到不适当的ContentType时取消导航 .

    System.Net.WebRequest request = System.Net.WebRequest.Create(e.Url);
    
    // we need only header part of http response
    request.Method = "HEAD";
    
    System.Net.WebResponse response = request.GetResponse();
    
    // only text/html, text/xml, text/plain are allowed... extend as required
    if (!response.ContentType.StartsWith("text/"))
    {
      e.Cancel = true;
      MessageBox.Show("Not allowed for security resons...");
    }
    

    显然这不是防弹解决方案,但可以让你知道如何开始(如果你不介意额外的微小往返只是为了检索http响应头) .

    Jens Bannmann写道:这不是理想的,因为我正在处理Web应用程序,其中额外的请求可能会触发两次执行的操作:-(

    然后我将创建一个简单的代理服务器来检查所有收到的数据,并过滤掉所有可能在您的Web浏览器控件中触发“另存为”对话框的http响应 .

    简单地说,不要让您的Web浏览器控件直接访问Internet,而是将所有http请求委派给您的特殊代理服务器,该服务器将过滤掉来自Web的所有不安全响应 .

  • 3

    唯一可靠的方法似乎是挂钩到Windows事件队列并禁止显示对话框(因为各种事情都可以让用户访问) . 这是我们的助手类所做的:

    void ListenForDialogCreation()
        {
            // Listen for name change changes across all processes/threads on current desktop...
            _WinEventHook = WinAPI.SetWinEventHook(WinAPI.EVENT_OBJECT_CREATE, procDelegate);
        }
        void StopListeningForDialogCreation()
        {
            WinAPI.UnhookWinEvent(_WinEventHook);
        }
    
        void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            const uint OBJID_WINDOW = 0;
            const uint CHILDID_SELF = 0;
    
            // filter out non-HWND, and things not children of the current application
            if (idObject != OBJID_WINDOW || idChild != CHILDID_SELF)
                return;
    
            //Get the window class name
            StringBuilder ClassName = new StringBuilder(100);
            WinAPI.GetClassName(hwnd, ClassName, ClassName.Capacity);
    
            // Send close message to any dialog
            if (ClassName.ToString() == "#32770")
            {
                WinAPI.SendMessage(hwnd, WinAPI.WM.CLOSE, IntPtr.Zero, IntPtr.Zero);
                if (OnDialogCancelled != null)
                    OnDialogCancelled();
            }
            if (ClassName.ToString() == "#32768")
            {
                WinAPI.SendMessage(hwnd, WinAPI.WM.CLOSE, IntPtr.Zero, IntPtr.Zero);
                if (OnDialogCancelled != null)
                    OnDialogCancelled();
            }
    
        }
    
        public delegate void OnDialogCancelledEvent();
        public event OnDialogCancelledEvent OnDialogCancelled;
    
    • #32770是Dialog类

    • #32768是弹出菜单

    • WinAPI命名空间是我们的pinvoke包装器 .

    如果您不想阻止所有对话,那么一旦您上课,您就会想要添加一些额外的过滤器 . 这取决于你需要多么安全 . 在$ WORK,我们需要阻止所有上传和下载 .

    禁止弹出菜单是必要的,因为它可以访问帮助应用程序,该应用程序提供了微软网站的链接,可以启动IE的完整实例 . 然后他们可以做任何他们想做的事 .

  • 3

    此项目 - http://www.codeproject.com/Articles/157329/Http-Monitor-for-Webbrowser-Control允许拦截和检查来自WebBrowser控件的HTTP流量 .

    然后你可以通过MIME过滤数据,只允许html,图像,脚本等 .

相关问题