chromium - отправлять информацию о пользовательском заголовке при начальной загрузке страницы С#

Или Как вставить пользовательский заголовок в первоначальный запрос к сайту при обновлении экземпляра ChromiumWebBrowser.

Я нуб с Chromium, и мне действительно нужна помощь. У меня есть приложение winforms с окном CEF. К., пока без проблем. Что мне нужно сделать, так это вызвать/загрузить начальный URL-адрес с пользовательским http-заголовком, который содержит информацию для аутентификации. Это возможно?

Ниже приведено, по сути, то, что в игре, и все части работают, кроме пользовательского заголовка (Doh!)

Winform (CEF httpRequest (с настраиваемым заголовком)) [никогда не проходит эту точку] => Веб-приложение C# MVC => Сегмент Owin_Authentication_Pipeline => Ответ MVC с заполненным представлением Razor => Отображается в приложении Winform Chromium.

Возможно, это тоже поможет:

using CefSharp;
using CefSharp.WinForms;
...
private void Form1_Load(object sender, EventArgs e)
{
    Cef.Initialize();
    ChromiumWebBrowser myBrowser = new ChromiumWebBrowser("whatever.com");
    // ??How do i get a custom header be sent with the above line??

    myBrowser.Dock = DockStyle.Fill;
    //myBrowser.ShowDevTools();
    //myBrowser.RequestHandler = new DSRequestHander();
    //myBrowser.FrameLoadStart += myBrowser_FrameLoadStart;
    this.Controls.Add(myBrowser);
}

Я проглотил это до смерти, посмотрел, перепробовал все приемы в моем наборе инструментов, а затем и некоторые другие.

Любые идеи, помощь или подсказки о том, как я мог бы решить или обойти это boggler, очень ценятся. Заранее спасибо.


person JackJack    schedule 06.07.2015    source источник
comment
Вы используете проект CEFSharp? github.com/cefsharp/CefSharp/wiki   -  person NinjaMid76    schedule 06.07.2015
comment
@ NinjaMid76 Да, да, я.   -  person JackJack    schedule 07.07.2015
comment
Почти невозможно помочь вам, если вы не поделитесь дополнительной информацией, например. от того, как далеко в этой цепочке компонентов продвинулся ваш собственный заголовок. Появляется ли он в сегменте Owin_Authentication_Pipeline? Он отвергает это? И т. д. и т. д. Предоставьте нам базовую информацию об отладке того, что вы пробовали. У хороших вопросов stackoverflow есть MVCE.   -  person jornh    schedule 09.07.2015
comment
@jornh ..расслабься. не надо хулиганства. И «нет» он не достигает собственного конвейера. Вопрос заключается в том, как внедрить собственный заголовок в первоначальный запрос на сайт при обновлении ChromiumWebBrowser. Я отредактировал вопрос, чтобы уточнить. Спасибо за ваш отзыв. Здорово... все хорошо.   -  person JackJack    schedule 10.07.2015
comment
Никакого намерения очернить вообще - просто хочу убрать как можно больше догадок, чтобы лучше иметь возможность предложить помощь :-). Ваши правки очень помогли в этом! Пробовали ли вы что-то вроде groups.google.com/forum/ m/#!topic/cefsharp/Yi9bWHmASQU ? Этот пост немного устарел, не уверен, изменился ли API с тех пор.   -  person jornh    schedule 10.07.2015
comment
API немного изменился, хотя концепция почти та же. Некоторое время назад я разделил Request и Response на два отдельных объекта. В какой-то момент мы, вероятно, должны обернуть базовый объект HeaderMap, чтобы обеспечить более приятный API.   -  person amaitland    schedule 12.07.2015
comment
Хотя этот проект изменился из проекта CEFSharp, я собираюсь поработать над простым доказательством концепции (если это еще не сделано) и опубликовать его на Github для всех, кому это может быть интересно. Спасибо всем, кто прокомментировал этот вопрос. -феликсд   -  person JackJack    schedule 23.03.2017


Ответы (3)


Обновлено с учетом основных изменений Chromium

Обновлено, чтобы отразить изменения, внесенные в версию 75 (должно работать в 75 и новее)

Метод, который вам нужен, должен быть OnBeforeResourceLoad, базовый пример должен выглядеть так:

public class CustomResourceRequestHandler : ResourceRequestHandler
{
    protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
    {
        var headers = request.Headers;
        headers["User-Agent"] = "My User Agent";
        request.Headers = headers;

        return CefReturnValue.Continue;
    }
}

public class CustomRequestHandler : RequestHandler
{
    protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
    {
        return new CustomResourceRequestHandler();
    }
}

browser.RequestHandler = new CustomRequestHandler();

Используя свойство IRequest.Headers, вы должны прочитать свойство заголовков, внести изменения, а затем переназначить его. Теперь можно использовать функции SetHeaderByName/GetHeaderByName для получения/установки одного заголовка.

person amaitland    schedule 12.07.2015
comment
Я создал класс CustomChromeBrowser, унаследованный от ChromiumWebBrowser, и назначил класс RequestHandler (поставляется с демонстрационным проектом) через событие Initialized класса CustomChromeBrowser. - person CodingYourLife; 19.05.2016
comment
Все Handlers являются простыми свойствами, их достаточно задать в конструкторе. - person amaitland; 19.05.2016
comment
Можем ли мы получить более подробную информацию, пожалуйста, у меня такая же проблема, и я не уверен, что понимаю, как делать то, что вы предлагаете. - person Psddp; 15.12.2016
comment
Это не работает для меня. Свойство Headers запроса просто не меняется. Никаких исключений не выбрасывается, оно просто не будет обновляться. Headers.IsReadOnly имеет значение false. - person scatter; 10.07.2018
comment
@amaitland Будет ли это автоматически применяться к запросам страниц и запросам ajax? Меня в основном интересует изменение запросов ajax и как это сделать. Похоже, так и должно быть, потому что я не вижу других способов выполнить сканирование документа API. В любом случае, ваше слово примет мое дизайнерское решение и не даст мне двигаться в другом направлении. - person Carter; 29.05.2020
comment
Все запросы, напрямую связанные с браузером, должны проходить здесь. Вы можете использовать cefsharp.github.io/api/81.3.x/html / для обработки уровня RequestContext. Если у вас возникли проблемы с выделением только запросов Ajax, задайте новый вопрос. - person amaitland; 29.05.2020
comment
См. github.com/cefsharp/CefSharp/wiki/ для получения дополнительной информации о RequestContext. Запросы из памяти от Service Workers будут доступны только через обработку уровня RequestContext, поскольку они не обязательно напрямую связаны с браузером. - person amaitland; 29.05.2020
comment
@amaitland Спасибо! вы отлично справляетесь с CefSharp. Работает как шарм, спасибо за все, что вы делаете. +3 - person Carter; 01.06.2020

Вы должны создать класс, который реализует IRequestHandler, а затем установить экземпляр этого класса как RequestHandler в объекте вашего браузера.

В версии 53 этот класс должен выглядеть так:

class ChromeBrowserRequestHandler: IRequestHandler
    {
        public bool GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
        {
            return false;
        }

        public bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect)
        {
            return false;
        }

        public bool OnBeforePluginLoad(IWebBrowser browser, string url, string policyUrl, WebPluginInfo info)
        {
            return false;
        }

        public CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
        {
            var headers = request.Headers;
            headers["Custom-Header"] = "My Custom Header";
            request.Headers = headers;

            return CefReturnValue.Continue;
        }

        public bool OnCertificateError(IWebBrowser browser, CefErrorCode errorCode, string requestUrl)
        {
            return false;
        }

        public void OnPluginCrashed(IWebBrowser browser, string pluginPath)
        {
        }

        public void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status)
        {
        }

        public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) 
        { 
            return null; 
        }

        public bool OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) 
        {
            return false; 
        }

        public bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) 
        {
            return false; 
        }

        public void OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath) 
        {
        }

        public bool OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url) 
        {
            return false;
        }

        public bool OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize, IRequestCallback callback) 
        {
            return false;
        }

        public void OnRenderViewReady(IWebBrowser browserControl, IBrowser browser) 
        { 
        }

        public void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        { 
        }

        public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, ref string newUrl) 
        { 
        }

        public bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) 
        {
            return false;
        }
    }

Затем при создании объекта браузера:

ChromiumWebBrowser myBrowser = new ChromiumWebBrowser("whatever.com")
{
    RequestHandler = new ChromeBrowserRequestHandler()
};

Обратите внимание, что обработчик запроса должен быть установлен до загрузки страницы. Если вы не можете установить обработчик запроса во время создания экземпляра, вы все равно можете установить его позже, перезагрузив страницу с помощью myBrowser.Load("whatever.com") .

person Psddp    schedule 15.12.2016
comment
Используя версию 47.0.2.0, я не вижу никаких изменений в заголовках запросов в инструментах разработки. - person Josh Noe; 05.01.2021

В одной из последних версий некоторые обратные вызовы были перемещены из интерфейса IRequestHandler в интерфейс IResourceRequestHandler. Самый простой способ - переопределить реализации по умолчанию RequestHandler и ResourceRequestHandler, например:

class BearerAuthResourceRequestHandler : ResourceRequestHandler
    {
        public BearerAuthResourceRequestHandler(string token)
        {
            _token = token;
        }

        private string _token;

        protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
        {
            if (!string.IsNullOrEmpty(_token))
            {
                var headers = request.Headers;
                headers["Authorization"] = $"Bearer {_token}";
                request.Headers = headers;
                return CefReturnValue.Continue;
            }
            else return base.OnBeforeResourceLoad(chromiumWebBrowser, browser, frame, request, callback);
        }

    }
    class BearerAuthRequestHandler : RequestHandler
    {
        public BearerAuthRequestHandler(string token)
        {
            _token = token;
        }

        private string _token;

        protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
        {
            if (!string.IsNullOrEmpty(_token)) return new BearerAuthResourceRequestHandler(_token);
            else return base.GetResourceRequestHandler(chromiumWebBrowser, browser, frame, request, isNavigation, isDownload, requestInitiator, ref disableDefaultHandling);
        }
    }

Затем назначьте его браузеру RequestHandler:

Browser.RequestHandler = new BearerAuthRequestHandler(token);
person Evgeniy Vaganov    schedule 31.07.2019