Как заблокировать загрузку в элементе управления .NET WebBrowser?
Мне нужно запретить элементу управления .NET WebBrowser показывать "Вы хотите открыть или сохранить этот файл?". и "Сохранить как". Вместо этого я хочу отобразить окно сообщения, сообщающее пользователям, что загрузка файлов отключена по соображениям безопасности.
Я начал с события FileDownload
WebBrowser
, но он не позволяет отменить. Затем я использовал подход CodeProject: Extended.NET 2.0 WebBrowser Control для реализации моего собственного события на основе исходного COM-вызова с использованием интерфейса DWebBrowserEvents2
. Когда я исправил код в соответствии с записью базы знаний MS о ошибке с подписью FileDownload, обработчик события был вызван, и я смог отмените загрузку.
Однако это не работает со всеми загрузками: загрузите URL-адреса, указывающие на URL-адрес, включая .exe
, поднимите событие и можно отменить до появления диалогового окна, но для других (например, .do
) обработчик событий не до тех пор, пока пользователь не нажимает Open
, Save
или Cancel
в диалоговом окне.
Возможным решением может быть перехватить сообщения WH_CALLWNDPROCRET
и "ответить" на диалог до того, как он будет показан пользователю, но это звучит как много усилий, и я также предпочел бы более чистое решение...
Кто-нибудь знает, как надежно блокировать все загрузки?
Ответы
Ответ 1
Вы можете использовать событие 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 писал (а):
Это не идеально, поскольку я имею дело с веб-приложениях, где дополнительные запрос может инициировать действие, являющееся выполняется дважды: - (
Затем я бы создал простейший прокси-сервер, который бы проверял все полученные данные и отфильтровывал все HTTP-ответы, которые могли бы вызвать диалог "Сохранить как" в вашем веб-браузере.
Просто не позволяйте своему веб-браузеру напрямую обращаться к Интернету, но делегируйте все HTTP-запросы на ваш специальный прокси-сервер, который будет отфильтровывать все небезопасные ответы из Интернета.
Ответ 2
Единственный надежный способ - подключиться к очереди событий 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 нам нужно было блокировать все загрузки и загрузки.
Подавление всплывающего меню необходимо, так как оно дает доступ к приложению справки, которое дает ссылки на веб-сайт Microsoft, который позволяет запускать полный экземпляр IE. Тогда они могут делать все, что захотят.
Ответ 3
Этот проект http://www.codeproject.com/Articles/157329/Http-Monitor-for-Webbrowser-Control позволяет перехватывать и проверять HTTP-трафик с помощью элемента управления WebBrowser.
Затем вы можете фильтровать данные с помощью MIME и разрешать только html, изображения, скрипты и т.д.