问题
Or How to inject a custom header into the initial request to a site when new-ing up an instance of the ChromiumWebBrowser.
I'm a noob with Chromium and could really use some help. I have a winforms app with a CEF window. K, no prob so far. What I need to do is to call/load the initial url with a custom http-header that contains authentication info. Is this possible?
The following is essentially what is at play and all parts work except the custom header (Doh!)
Winform(CEF httpRequest(with custom header)) [never gets past this point]=> C# MVC web app => Owin_Authentication_Pipeline segment => MVC Response with populated Razor view => Shows up in Winform Chromium app.
Maybe this will help as well:
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);
}
I Groggled this to death, looked, tried all the tricks in my toolbox and then some.
Any ideas, help or hints on how I might be able to solve or get around this boggler is greatly appreciated. Thanks in advance.
回答1:
Updated to reflect major Chromium changes
Updated to reflect changes made in version 75
(should work in 75
and newer)
The method your after should be OnBeforeResourceLoad
, a basic example should look like.
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();
Using the IRequest.Headers
property you must read the headers property, make changes then reassign it. It's now possible to use the SetHeaderByName/GetHeaderByName
functions to get/set a single header.
- RequestHandler API Doc
- ResourceRequestHandler API Doc
- IRequest.GetHeaderByName API Doc
- IRequest.SetHeaderByName API Doc
回答2:
You should create a class that implement IRequestHandler
then set an instance of that class as RequestHandler
in your browser object.
With version 53, that class should look like:
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;
}
}
Then, while creating your browser object:
ChromiumWebBrowser myBrowser = new ChromiumWebBrowser("whatever.com")
{
RequestHandler = new ChromeBrowserRequestHandler()
};
Note that the request handler must be set before loading the page. If you can't set the request handler during instanctiaction, you can still set it later a reload the page with myBrowser.Load("whatever.com")
.
回答3:
In the one of the latest versions some callbacks have been moved from IRequestHandler
to IResourceRequestHandler
interface. Simplest way is to override default implementations RequestHandler
& ResourceRequestHandler
, for example:
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);
}
}
Then, assign it to browser RequestHandler
:
Browser.RequestHandler = new BearerAuthRequestHandler(token);
来源:https://stackoverflow.com/questions/31250797/chromium-send-custom-header-info-on-initial-page-load-c-sharp