c# Cefsharp 83.x 拦截request请求、response响应、cookie等

winform的Cefsharp 83.x版本对原来的 IRequestHandler 接口做了调整,

以前的版本在 IRequestHandler 里有 GetResourceResponseFilter 接口,可以对response数据进行过滤、修改,但是最近更新了新版之后发现接口不见了,然后搜了好久没搜到,能搜到的都是很老的版本。后来在源码里去找了半天才发现接口位置给换地方了。

现在的接口位置位于 IRequestHandler.GetResourceRequestHandler -> IResourceRequestHandler.GetResourceResponseFilter

这次主要是拦截get返回的数据,所以写了个简单的拦截类,顺便把官方的注释搬了过来。主要有3个文件。

功能:

1、如果要取消某个 request ,可以在 OnBeforeBrowse 返回true。

2、如果要替换响应流,也就是替换网页内容,可以 MyResponseFilter.Filter 里对 dataOut 进行赋值即可。

3、如果要替换响应的cookie,MyResourceRequestHandler.GetCookieAccessFilter 里进行操作即可

4、如果要修改 request 内容,根据官方注释,目前没有找到能在请求之前可以对 IRequest request 参数进行修改的方法

只在 MyResourceRequestHandler -> GetResourceHandler  OnBeforeResourceLoad 这两个方法中可以对 request 参数的url进行修改(相当于重定向)

调用方法:


        //要捕获的url, "mainPage"只是url的简称,不做计算用
Dictionary<string, string> FilterUrls = new Dictionary<string, string>()
            {
                {"mainPage","https://www.baidu.com" },
            };

            #region  自定义捕获或过滤
            //new有很多重载方法,由于我这次用默认全是GET,所以没有定义请求类型
            MyRequestHandler = new MyRequestHandler(FilterUrls);
            browser.RequestHandler = MyRequestHandler;
            #endregion
            //整个类打印
            var str =MyRequestHandler.ToString();
//提取某一个url拦截的数据
var fd = MyRequestHandler.Filters.FirstOrDefault(f => f.Name == "mainPage");
var HasData = fd?.HasData;
            var data = fd?.Filter?.DataStr;
//关闭brower时必须Dispose
            MyRequestHandler.Dispose();

1、MyRequestHandler.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using CefSharp;

namespace cefBrowser.browser.handler
    {
    public enum HttpMethod
        {
        None,
        GET,
        POST,
        CONNECT,
        OPTIONS,
        }
    public class FilterData: IDisposable
        {
        public FilterData(string name, string url) { Name = name; Url = url; }
        public FilterData(string name, string url, HttpMethod _Method) { Name = name; Url = url; Method = _Method; }
        /// <summary>
        /// 别名
        /// </summary>
        public string Name { get; set; }
        public string Url { get; set; }
        public HttpMethod Method { get; set; } = HttpMethod.GET;
        public bool HasData { get { return Filter?.Data?.Length  > 0; } }
        public UInt64 Identifier { get; set; }
        public MyResponseFilter Filter { get; set; }
        public void AddFilter(UInt64 _Identifier, MyResponseFilter _Filter)
            {
            Filter?.Dispose(true);
            Identifier = _Identifier;
            Filter = _Filter;
            }

        bool Disposed = false;
        public void Dispose()
            {
            if (Disposed)
                return;
            Filter?.Dispose(true);
            Disposed = true;
            }
        public override string ToString()
            {
            return $"Name={Name},DataStr={Filter?.DataStr}";
            }
        }

    class MyRequestHandler : IRequestHandler,IDisposable
        {
        public MyRequestHandler(string name, string _url, HttpMethod _Method = HttpMethod.GET, bool _filter = false)
            {
            Filters.Add(new FilterData(name, _url, _Method));
            filter = _filter;
            }
        public MyRequestHandler(Dictionary<string,string> _urls, HttpMethod _Method =  HttpMethod.GET, bool _filter = false)
            {
            foreach(var u in _urls)
                {
                Filters.Add(new FilterData(u.Key, u.Value, _Method));
                }
            filter = _filter;
            }
        public MyRequestHandler(FilterData Filter, bool _filter = false)
            {
            Filters.Add(Filter);
            filter = _filter;
            }
        public MyRequestHandler(List<FilterData> _Filters, bool _filter = false)
            {
            Filters.AddRange(_Filters);
            filter = _filter;
            }

        bool Disposed = false;
        /// <summary>
        /// 是否过滤,如果不过滤就截获
        /// </summary>
        bool filter = false;
        /// <summary>
        /// 过滤、截获 url 列表 和 捕获过滤数据
        /// </summary>
        List<FilterData> Filters = new List<FilterData>();
        MyResourceRequestHandler handler;

        /// <summary>
        /// 证书认证
        /// Called when the browser needs credentials from the user.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        /// <param name="originUrl">is the origin making this authentication request.</param>
        /// <param name="isProxy">indicates whether the host is a proxy server.</param>
        /// <param name="host">hostname.</param>
        /// <param name="port">port number.</param>
        /// <param name="realm">realm.</param>
        /// <param name="scheme">scheme.</param>
        /// <param name="callback">Callback interface used for asynchronous continuation of authentication requests.</param>
        /// <returns>
        /// Return true to continue the request and call <see cref="IAuthCallback.Continue(string, string)"/> when the authentication
        /// information is available. Return false to cancel the request.
        /// </returns>
        bool IRequestHandler.GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
            { //NOTE: We also suggest you explicitly Dispose of the callback as it wraps an unmanaged resource.

            //Example #1
            //Spawn a Task to execute our callback and return true;
            //Typical usage would see you invoke onto the UI thread to open a username/password dialog
            //Then execute the callback with the response username/password
            //You can cast the IWebBrowser param to ChromiumWebBrowser to easily access
            //control, from there you can invoke onto the UI thread, should be in an async fashion
            //Load https://httpbin.org/basic-auth/cefsharp/passwd in the browser to test

            //Task.Run(() =>
            //{
            //    using (callback)
            //        {
            //        if (originUrl.Contains("https://httpbin.org/basic-auth/"))
            //            {
            //            var parts = originUrl.Split('/');
            //            var username = parts[parts.Length - 2];
            //            var password = parts[parts.Length - 1];
            //            callback.Continue(username, password);
            //            }
            //        }
            //});

            return true;

            //Example #2
            //Return false to cancel the request
            //callback.Dispose();
            //return false;
            }

        /// <summary>
        /// Called on the CEF IO thread before a resource request is initiated.
        /// </summary>
        /// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
        /// <param name="browser">represent the source browser of the request.</param>
        /// <param name="frame">represent the source frame of the request.</param>
        /// <param name="request">represents the request contents and cannot be modified in this callback.</param>
        /// <param name="isNavigation">will be true if the resource request is a navigation.</param>
        /// <param name="isDownload">will be true if the resource request is a download.</param>
        /// <param name="requestInitiator">is the origin (scheme + domain) of the page that initiated the request.</param>
        /// <param name="disableDefaultHandling">[in,out] to true to disable default handling of the request, in which case it will need
        /// to be handled via <see cref="IResourceRequestHandler.GetResourceHandler"/> or it will be canceled.</param>
        /// <returns>
        /// To allow the resource load to proceed with default handling return null. To specify a handler for the resource return a
        /// <see cref="IResourceRequestHandler"/> object. If this callback returns null the same method will be called on the associated
        /// <see cref="IRequestContextHandler"/>, if any.
        /// </returns>
        IResourceRequestHandler IRequestHandler.GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
            {
            var fd = Filters.FirstOrDefault(u => request.Url.Contains(u.Url) && (u.Method == HttpMethod.None ||  $"{u.Method}".ToLower() == request.Method.ToLower()));
            if (fd != null)
                {
                handler = new MyResourceRequestHandler(fd, filter);
                return handler;
                }
            return null;
            }

        /// <summary>
        /// Called before browser navigation. If the navigation is allowed <see cref="IWebBrowser.FrameLoadStart"/> and
        /// <see cref="IWebBrowser.FrameLoadEnd"/>
        /// will be called. If the navigation is canceled <see cref="IWebBrowser.LoadError"/> will be called with an ErrorCode value of
        /// <see cref="CefErrorCode.Aborted"/>.
        /// </summary>
        /// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        /// <param name="frame">The frame the request is coming from.</param>
        /// <param name="request">the request object - cannot be modified in this callback.</param>
        /// <param name="userGesture">The value will be true if the browser navigated via explicit user gesture (e.g. clicking a link) or
        /// false if it navigated automatically (e.g. via the DomContentLoaded event).</param>
        /// <param name="isRedirect">has the request been redirected.</param>
        /// <returns>
        /// Return true to cancel the navigation or false to allow the navigation to proceed.
        /// </returns>
        bool IRequestHandler.OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
            {
            return false;
            }

        /// <summary>
        /// Called to handle requests for URLs with an invalid SSL certificate. Return true and call
        /// <see cref="IRequestCallback.Continue"/> either in this method or at a later time to continue or cancel the request.  
        /// If CefSettings.IgnoreCertificateErrors is set all invalid certificates will be accepted without calling this method.
        /// </summary>
        /// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        /// <param name="errorCode">the error code for this invalid certificate.</param>
        /// <param name="requestUrl">the url of the request for the invalid certificate.</param>
        /// <param name="sslInfo">ssl certificate information.</param>
        /// <param name="callback">Callback interface used for asynchronous continuation of url requests. If empty the error cannot be
        /// recovered from and the request will be canceled automatically.</param>
        /// <returns>
        /// Return false to cancel the request immediately. Return true and use <see cref="IRequestCallback"/> to execute in an async
        /// fashion.
        /// </returns>
        bool IRequestHandler.OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback)
            {
            //NOTE: We also suggest you wrap callback in a using statement or explicitly execute callback.Dispose as callback wraps an unmanaged resource.

            //Example #1
            //Return true and call IRequestCallback.Continue() at a later time to continue or cancel the request.
            //In this instance we'll use a Task, typically you'd invoke a call to the UI Thread and display a Dialog to the user
            //You can cast the IWebBrowser param to ChromiumWebBrowser to easily access
            //control, from there you can invoke onto the UI thread, should be in an async fashion

            //Task.Run(() =>
            //{
            //    //NOTE: When executing the callback in an async fashion need to check to see if it's disposed
            //    if (!callback.IsDisposed)
            //        {
            //        using (callback)
            //            {
            //            //We'll allow the expired certificate from badssl.com
            //            if (requestUrl.ToLower().Contains("https://expired.badssl.com/"))
            //                {
            //                callback.Continue(true);
            //                }
            //            else
            //                {
            //                callback.Continue(false);
            //                }
            //            }
            //        }
            //});

            return true;

            //Example #2
            //Execute the callback and return true to immediately allow the invalid certificate
            //callback.Continue(true); //Callback will Dispose it's self once exeucted
            //return true;

            //Example #3
            //Return false for the default behaviour (cancel request immediately)
            //callback.Dispose(); //Dispose of callback
            //return false;
            }

        /// <summary>
        /// Called on the CEF UI thread when the window.document object of the main frame has been created.
        /// </summary>
        /// <param name="chromiumWebBrowser">the ChromiumWebBrowser control</param>
        /// <param name="browser">the browser object</param>
        void IRequestHandler.OnDocumentAvailableInMainFrame(IWebBrowser chromiumWebBrowser, IBrowser browser)
            {
            }

        /// <summary>
        /// Called on the UI thread before OnBeforeBrowse in certain limited cases where navigating a new or different browser might be
        /// desirable. This includes user-initiated navigation that might open in a special way (e.g. links clicked via middle-click or
        /// ctrl + left-click) and certain types of cross-origin navigation initiated from the renderer process (e.g. navigating the top-
        /// level frame to/from a file URL).
        /// </summary>
        /// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        /// <param name="frame">The frame object.</param>
        /// <param name="targetUrl">target url.</param>
        /// <param name="targetDisposition">The value indicates where the user intended to navigate the browser based on standard
        /// Chromium behaviors (e.g. current tab, new tab, etc).</param>
        /// <param name="userGesture">The value will be true if the browser navigated via explicit user gesture (e.g. clicking a link) or
        /// false if it navigated automatically (e.g. via the DomContentLoaded event).</param>
        /// <returns>
        /// Return true to cancel the navigation or false to allow the navigation to proceed in the source browser's top-level frame.
        /// </returns>
        bool IRequestHandler.OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
            {
            return false;
            }

        /// <summary>
        /// Called when a plugin has crashed.
        /// </summary>
        /// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        /// <param name="pluginPath">path of the plugin that crashed.</param>
        void IRequestHandler.OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath)
            {
            // TODO: Add your own code here for handling scenarios where a plugin crashed, for one reason or another.
            }

        /// <summary>
        /// Called when JavaScript requests a specific storage quota size via the webkitStorageInfo.requestQuota function. For async
        /// processing return true and execute <see cref="IRequestCallback.Continue"/> at a later time to grant or deny the request or
        /// <see cref="IRequestCallback.Cancel"/> to cancel.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        /// <param name="originUrl">the origin of the page making the request.</param>
        /// <param name="newSize">is the requested quota size in bytes.</param>
        /// <param name="callback">Callback interface used for asynchronous continuation of url requests.</param>
        /// <returns>
        /// Return false to cancel the request immediately. Return true to continue the request and call
        /// <see cref="IRequestCallback.Continue"/> either in this method or at a later time to grant or deny the request.
        /// </returns>
        bool IRequestHandler.OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback)
            {
            //NOTE: If you do not wish to implement this method returning false is the default behaviour
            // We also suggest you explicitly Dispose of the callback as it wraps an unmanaged resource.
            //callback.Dispose();
            //return false;

            //NOTE: When executing the callback in an async fashion need to check to see if it's disposed
            //if (!callback.IsDisposed)
            //    {
            //    using (callback)
            //        {
            //        //Accept Request to raise Quota
            //        //callback.Continue(true);
            //        //return true;
            //        }
            //    }

            return false;
            }

        /// <summary>
        /// Called when the render process terminates unexpectedly.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        /// <param name="status">indicates how the process terminated.</param>
        void IRequestHandler.OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status)
            {
            // TODO: Add your own code here for handling scenarios where the Render Process terminated for one reason or another.
            //chromiumWebBrowser.Load(CefExample.RenderProcessCrashedUrl);
            }

        /// <summary>
        /// Called on the CEF UI thread when the render view associated with browser is ready to receive/handle IPC messages in the
        /// render process.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        void IRequestHandler.OnRenderViewReady(IWebBrowser chromiumWebBrowser, IBrowser browser)
            {
            }

        /// <summary>
        /// Called when the browser needs user to select Client Certificate for authentication requests (eg. PKI authentication).
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object.</param>
        /// <param name="isProxy">indicates whether the host is a proxy server.</param>
        /// <param name="host">hostname.</param>
        /// <param name="port">port number.</param>
        /// <param name="certificates">List of Client certificates for selection.</param>
        /// <param name="callback">Callback interface used for asynchronous continuation of client certificate selection for
        /// authentication requests.</param>
        /// <returns>
        /// Return true to continue the request and call ISelectClientCertificateCallback.Select() with the selected certificate for
        /// authentication. Return false to use the default behavior where the browser selects the first certificate from the list.
        /// 
        /// </returns>
        bool IRequestHandler.OnSelectClientCertificate(IWebBrowser chromiumWebBrowser, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback)
            {
            //callback.Dispose();
            return false;
            }

        public override string ToString()
            {
            if (!Filters?.Any() ?? true)
                return string.Empty;
            return string.Join("\r\n", Filters.Select(f => f.ToString()));
            }
        public void Dispose()
            {
            if (Disposed)
                return;
            handler?.Dispose();
            Filters?.ForEach(f => f.Dispose());
            Filters?.Clear();
            Filters = null;
            Disposed = true;
            }
        }



    }

 

2、MyResourceRequestHandler.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;

namespace cefBrowser.browser.handler
    {
    class MyResourceRequestHandler : IResourceRequestHandler
        {
        public MyResourceRequestHandler(FilterData Filter, bool _filter)
            {
            filterData = Filter;
            filter = _filter;
            }

        bool Disposed = false;
        /// <summary>
        /// 是否过滤,如果不过滤就截获
        /// </summary>
        bool filter = false;
        /// <summary>
        /// 过滤、截获 url 列表 和 捕获过滤数据
        /// </summary>
        FilterData filterData { get; set; }


        /// <summary>
        /// Called on the CEF IO thread before a resource request is loaded. To optionally filter cookies for the request return a
        /// <see cref="ICookieAccessFilter"/> object.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="frame">the frame object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="request">the request object - can be modified in this callback.</param>
        /// <returns>To optionally filter cookies for the request return a ICookieAccessFilter instance otherwise return null.</returns>
        ICookieAccessFilter IResourceRequestHandler.GetCookieAccessFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request)
            {
            return null;
            }

        /// <summary>
        /// Called on the CEF IO thread before a resource is loaded. To specify a handler for the resource return a
        /// <see cref="IResourceHandler"/> object.
        /// </summary>
        /// <param name="chromiumWebBrowser">The browser UI control.</param>
        /// <param name="browser">the browser object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="frame">the frame object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="request">the request object - cannot be modified in this callback.</param>
        /// <returns>
        /// To allow the resource to load using the default network loader return null otherwise return an instance of
        /// <see cref="IResourceHandler"/> with a valid stream.
        /// </returns>
        IResourceHandler IResourceRequestHandler.GetResourceHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request)
            {
            return null;
            }

        /// <summary>Called on the CEF IO thread to optionally filter resource response content.</summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="frame">the frame object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="request">the request object - cannot be modified in this callback.</param>
        /// <param name="response">the response object - cannot be modified in this callback.</param>
        /// <returns>Return an IResponseFilter to intercept this response, otherwise return null.</returns>
        IResponseFilter IResourceRequestHandler.GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
            {
            var fil = new MyResponseFilter(filter);
            filterData.AddFilter(request.Identifier, fil);
            return fil;
            }

        /// <summary>
        /// Called on the CEF IO thread before a resource request is loaded. To redirect or change the resource load optionally modify
        /// <paramref name="request"/>. Modification of the request URL will be treated as a redirect.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="frame">the frame object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="request">the request object - can be modified in this callback.</param>
        /// <param name="callback">Callback interface used for asynchronous continuation of url requests.</param>
        /// <returns>
        /// Return <see cref="CefReturnValue.Continue"/> to continue the request immediately. Return
        /// <see cref="CefReturnValue.ContinueAsync"/> and call <see cref="IRequestCallback.Continue"/> or
        /// <see cref="IRequestCallback.Cancel"/> at a later time to continue or the cancel the request asynchronously. Return
        /// <see cref="CefReturnValue.Cancel"/> to cancel the request immediately.
        /// </returns>
        CefReturnValue IResourceRequestHandler.OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
            {
            //Uri url;
            //if (Uri.TryCreate(request.Url, UriKind.Absolute, out url) == false)
            //    {
            //    //If we're unable to parse the Uri then cancel the request
            //    // avoid throwing any exceptions here as we're being called by unmanaged code
            //    return CefReturnValue.Cancel;
            //    }

            //Example of how to set Referer
            // Same should work when setting any header

            // For this example only set Referer when using our custom scheme
            //if (url.Scheme == CefSharpSchemeHandlerFactory.SchemeName)
            //    {
            //    //Referrer is now set using it's own method (was previously set in headers before)
            //    request.SetReferrer("http://google.com", ReferrerPolicy.Default);
            //    }

            //Example of setting User-Agent in every request.
            //var headers = request.Headers;

            //var userAgent = headers["User-Agent"];
            //headers["User-Agent"] = userAgent + " CefSharp";

            //request.Headers = headers;

            //NOTE: If you do not wish to implement this method returning false is the default behaviour
            // We also suggest you explicitly Dispose of the callback as it wraps an unmanaged resource.
            //callback.Dispose();
            //return false;

            //NOTE: When executing the callback in an async fashion need to check to see if it's disposed
            //if (!callback.IsDisposed)
            //    {
            //    using (callback)
            //        {
            //        if (request.Method == "POST")
            //            {
            //            using (var postData = request.PostData)
            //                {
            //                if (postData != null)
            //                    {
            //                    var elements = postData.Elements;

            //                    var charSet = request.GetCharSet();

            //                    foreach (var element in elements)
            //                        {
            //                        if (element.Type == PostDataElementType.Bytes)
            //                            {
            //                            var body = element.GetBody(charSet);
            //                            }
            //                        }
            //                    }
            //                }
            //            }

            //        //Note to Redirect simply set the request Url
            //        //if (request.Url.StartsWith("https://www.google.com", StringComparison.OrdinalIgnoreCase))
            //        //{
            //        //    request.Url = "https://github.com/";
            //        //}

            //        //Callback in async fashion
            //        //callback.Continue(true);
            //        //return CefReturnValue.ContinueAsync;
            //        }
            //    }

            return CefReturnValue.Continue;
            }

        /// <summary>
        /// Called on the CEF UI thread to handle requests for URLs with an unknown protocol component. SECURITY WARNING: YOU SHOULD USE
        /// THIS METHOD TO ENFORCE RESTRICTIONS BASED ON SCHEME, HOST OR OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="frame">the frame object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="request">the request object - cannot be modified in this callback.</param>
        /// <returns>
        /// return to true to attempt execution via the registered OS protocol handler, if any. Otherwise return false.
        /// </returns>
        bool IResourceRequestHandler.OnProtocolExecution(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request)
            {

            //return request.Url.StartsWith("mailto");
            return false;
            }

        /// <summary>
        /// Called on the CEF IO thread when a resource load has completed. This method will be called for all requests, including
        /// requests that are aborted due to CEF shutdown or destruction of the associated browser. In cases where the associated browser
        /// is destroyed this callback may arrive after the <see cref="ILifeSpanHandler.OnBeforeClose"/> callback for that browser. The
        /// <see cref="IFrame.IsValid"/> method can be used to test for this situation, and care
        /// should be taken not to call <paramref name="browser"/> or <paramref name="frame"/> methods that modify state (like LoadURL,
        /// SendProcessMessage, etc.) if the frame is invalid.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="frame">the frame object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="request">the request object - cannot be modified in this callback.</param>
        /// <param name="response">the response object - cannot be modified in this callback.</param>
        /// <param name="status">indicates the load completion status.</param>
        /// <param name="receivedContentLength">is the number of response bytes actually read.</param>
        void IResourceRequestHandler.OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
            {
            //var url = new Uri(request.Url);
            //if (url.Scheme == CefSharpSchemeHandlerFactory.SchemeName && memoryStream != null)
            //    {
            //    //TODO: Do something with the data here
            //    var data = memoryStream.ToArray();
            //    var dataLength = data.Length;
            //    //NOTE: You may need to use a different encoding depending on the request
            //    var dataAsUtf8String = Encoding.UTF8.GetString(data);
            //    }
            }

        /// <summary>
        /// Called on the CEF IO thread when a resource load is redirected. The <paramref name="request"/> parameter will contain the old
        /// URL and other request-related information. The <paramref name="response"/> parameter will contain the response that resulted
        /// in the redirect. The <paramref name="newUrl"/> parameter will contain the new URL and can be changed if desired.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="frame">the frame object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="request">the request object - cannot be modified in this callback.</param>
        /// <param name="response">the response object - cannot be modified in this callback.</param>
        /// <param name="newUrl">[in,out] the new URL and can be changed if desired.</param>
        void IResourceRequestHandler.OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl)
            {
            //Example of how to redirect - need to check `newUrl` in the second pass
            //if (request.Url.StartsWith("https://www.google.com", StringComparison.OrdinalIgnoreCase) && !newUrl.Contains("github"))
            //{
            //    newUrl = "https://github.com";
            //}
            }

        /// <summary>
        /// Called on the CEF IO thread when a resource response is received. To allow the resource load to proceed without modification
        /// return false. To redirect or retry the resource load optionally modify <paramref name="request"/> and return true.
        /// Modification of the request URL will be treated as a redirect. Requests handled using the default network loader cannot be
        /// redirected in this callback.
        /// 
        /// WARNING: Redirecting using this method is deprecated. Use OnBeforeResourceLoad or GetResourceHandler to perform redirects.
        /// </summary>
        /// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
        /// <param name="browser">the browser object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="frame">the frame object - may be null if originating from ServiceWorker or CefURLRequest.</param>
        /// <param name="request">the request object.</param>
        /// <param name="response">the response object - cannot be modified in this callback.</param>
        /// <returns>
        /// To allow the resource load to proceed without modification return false. To redirect or retry the resource load optionally
        /// modify <paramref name="request"/> and return true. Modification of the request URL will be treated as a redirect. Requests
        /// handled using the default network loader cannot be redirected in this callback.
        /// </returns>
        bool IResourceRequestHandler.OnResourceResponse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
            {
            //NOTE: You cannot modify the response, only the request
            // You can now access the headers
            //var headers = response.Headers;

            return false;
            }

        public void Dispose()
            {
            if (Disposed)
                return;
            Disposed = true;
            }
        }
    }

 

3、MyResponseFilter.cs

using CefSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace cefBrowser.browser.handler
    {
    public class MyResponseFilter : IResponseFilter
        {
        public MyResponseFilter(bool _filter) { filter = _filter; }

        bool Disposed = false;
        /// <summary>
        /// 是否过滤,如果不过滤就截获
        /// </summary>
        bool filter = false;
        private MemoryStream memoryStream;
        public void Dispose()
        {
            //memoryStream?.Dispose();
            //memoryStream = null;
            }
        public void Dispose(bool r)
            {
            if (Disposed)
                return;
            if (r)
                {
                memoryStream?.Dispose();
                memoryStream = null;
                }
            Disposed = true;
            }

        public FilterStatus Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten)
        {
            if (dataIn == null)
            {
                dataInRead = 0;
                dataOutWritten = 0;

                return FilterStatus.Done;
            }

            dataInRead = dataIn.Length;
            dataOutWritten = Math.Min(dataInRead, dataOut.Length);

            //Important we copy dataIn to dataOut
            dataIn.CopyTo(dataOut);

            //Copy data to stream
            dataIn.Position = 0;
            dataIn.CopyTo(memoryStream);

            return FilterStatus.Done;
        }

        public bool InitFilter()
        {
            memoryStream = new MemoryStream();

            return true;
        }
        public byte[] Data
        {
            get { return memoryStream.ToArray(); }
        }

        public string DataStr
            {
            get { return Encoding.UTF8.GetString(memoryStream.ToArray()); }
            }
    }
}

 

 

 

 

 

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页