Chromium - 在初始页面加载时发送自定义标头信息 c#

11

或者如何在实例化ChromiumWebBrowser时将自定义标头注入到网站的初始请求中。

我对Chromium并不了解,真的需要一些帮助。我有一个带有CEF窗口的winforms应用程序。目前为止还好。我需要做的是使用包含身份验证信息的自定义http标头调用/加载初始url。这可行吗?

以下基本上是所有部分都有效,除了自定义标头(糟糕!):

Winform(CEF httpRequest(带有自定义标头))[从未超过此点]=> C# MVC Web应用程序=> 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);
}

我已经拼命搜索了,试过了我的所有技巧和更多的方法。

对于我如何解决或绕过这个难题,任何想法、帮助或提示都将不胜感激。提前致谢。


1
你是否正在使用CEFSharp项目?https://github.com/cefsharp/CefSharp/wiki - NinjaMid76
@NinjaMid76 是的,是的,我就是。 - JackJack
如果您不分享更多信息,例如您的自定义标头在这些组件链中的哪个位置,那么帮助您几乎是不可能的。它是否出现在Owin_Authentication_Pipeline段?它是否被拒绝了?等等。请提供一些基本的调试信息,说明您已经尝试过什么。好的stackoverflow问题应该有一个MVCE(http://stackoverflow.com/help/mcve)。 - jornh
@jornh,冷静点。没有必要带有贬低的语气。而且,“不”,它并没有到达OWIN管道。问题是如何在新建一个ChromiumWebBrowser时将自定义标头注入到初始请求中。我已经编辑了问题以澄清。感谢您的反馈。干杯...一切都好。 - JackJack
绝不想贬低任何人-只是希望尽可能减少猜测,以便更好地提供帮助 :-)。您的编辑在这方面大有帮助!您是否尝试过类似于https://groups.google.com/forum/m/#!topic/cefsharp/Yi9bWHmASQU的内容?该帖子现在有点过时了,不确定API是否有所改变。 - jornh
显示剩余2条评论
3个回答

17

更新以反映重要的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函数来获取/设置单个标题。

我创建了一个 CustomChromeBrowser 类,继承自 ChromiumWebBrowser,并通过 CustomChromeBrowser 类的 Initialized 事件分配了一RequestHandler 类(随演示项目提供)。 - CodingYourLife
这对我不起作用。请求的 Headers 属性就是不会改变。没有抛出任何异常,它只是不会更新。Headers.IsReadOnly 为 false。 - scatter
@amaitland 这个会自动应用于页面请求和ajax请求吗?我主要想知道如何更改ajax请求以及如何实现。看起来应该可以,因为我没有看到其他扫描API文档的方法。无论如何,您的回复将有助于我的设计决策,并避免我走其他方向。 - Carter
1
所有与浏览器直接相关的请求都应通过这里进行处理。您可以使用http://cefsharp.github.io/api/81.3.x/html/M_CefSharp_IRequestContextHandler_GetResourceRequestHandler.htm来处理RequestContext。如果您在隔离Ajax请求方面遇到困难,请提出新问题。 - amaitland
1
请参阅 https://github.com/cefsharp/CefSharp/wiki/General-Usage#request-context-browser-isolation 了解RequestContext的背景细节。从记忆中,Service Worker发出的请求只能通过RequestContext级别的处理进行访问,因为它们不一定直接与浏览器相关联。 - amaitland
显示剩余3条评论

6

您需要创建一个实现 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")重新加载页面。

使用版本47.0.2.0,我在开发工具中没有看到请求头的任何更改。 - Josh Noe

5
在最新的版本中,一些回调函数已经从转移到了接口中。 最简单的方法是重写默认的实现RequestHandlerResourceRequestHandler,例如:
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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接