WinForm窗体程序中使用CefSharp获取加载后的资源、截取request参数、拦截response数据、注入jquery文件和js代码(3)-拦截response数据


源码地址:源代码csdn  或者底部qq问我要

五、cefsharp拦截response数据

与四类似,response数据也是要继承接口 IResourceRequestHandler,实现其方法,从方法中获取

1、添加类ResourceRequestHandler,继承IResourceRequestHandler,实现各种方法

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

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

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

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

        /// Called on the CEF IO thread to optionally filter resource response content.
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - cannot be modified in this callback.
        /// the response object - cannot be modified in this callback.
        /// Return an IResponseFilter to intercept this response, otherwise return null.
        IResponseFilter IResourceRequestHandler.GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            return GetResourceResponseFilter(chromiumWebBrowser, browser, frame, request, response);
        }

        /// Called on the CEF IO thread to optionally filter resource response content.
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - cannot be modified in this callback.
        /// the response object - cannot be modified in this callback.
        /// Return an IResponseFilter to intercept this response, otherwise return null.
        protected virtual IResponseFilter GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            return null;
        }

        /// 
        /// Called on the CEF IO thread before a resource request is loaded. To redirect or change the resource load optionally modify
        /// . Modification of the request URL will be treated as a redirect.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - can be modified in this callback.
        /// Callback interface used for asynchronous continuation of url requests.
        /// 
        /// Return  to continue the request immediately. Return
        ///  and call  or
        ///  at a later time to continue or the cancel the request asynchronously. Return
        ///  to cancel the request immediately.
        /// 
        CefReturnValue IResourceRequestHandler.OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
        {
            return OnBeforeResourceLoad(chromiumWebBrowser, browser, frame, request, callback);
        }

        /// 
        /// Called on the CEF IO thread before a resource request is loaded. To redirect or change the resource load optionally modify
        /// . Modification of the request URL will be treated as a redirect.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - can be modified in this callback.
        /// Callback interface used for asynchronous continuation of url requests.
        /// 
        /// Return  to continue the request immediately. Return
        ///  and call  or
        ///  at a later time to continue or the cancel the request asynchronously. Return
        ///  to cancel the request immediately.
        /// 
        protected virtual CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
        {
            return CefReturnValue.Continue;
        }

        /// 
        /// 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.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - cannot be modified in this callback.
        /// 
        /// return to true to attempt execution via the registered OS protocol handler, if any. Otherwise return false.
        /// 
        bool IResourceRequestHandler.OnProtocolExecution(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request)
        {
            return OnProtocolExecution(chromiumWebBrowser, browser, frame, request);
        }

        /// 
        /// 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.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - cannot be modified in this callback.
        /// 
        /// return to true to attempt execution via the registered OS protocol handler, if any. Otherwise return false.
        /// 
        protected virtual bool OnProtocolExecution(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request)
        {
            return false;
        }

        /// 
        /// 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  callback for that browser. The
        ///  method can be used to test for this situation, and care
        /// should be taken not to call  or  methods that modify state (like LoadURL,
        /// SendProcessMessage, etc.) if the frame is invalid.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - cannot be modified in this callback.
        /// the response object - cannot be modified in this callback.
        /// indicates the load completion status.
        /// is the number of response bytes actually read.
        void IResourceRequestHandler.OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        {
            OnResourceLoadComplete(chromiumWebBrowser, browser, frame, request, response, status, receivedContentLength);
        }

        /// 
        /// 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  callback for that browser. The
        ///  method can be used to test for this situation, and care
        /// should be taken not to call  or  methods that modify state (like LoadURL,
        /// SendProcessMessage, etc.) if the frame is invalid.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - cannot be modified in this callback.
        /// the response object - cannot be modified in this callback.
        /// indicates the load completion status.
        /// is the number of response bytes actually read.
        protected virtual void OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        {

        }

        /// 
        /// Called on the CEF IO thread when a resource load is redirected. The  parameter will contain the old
        /// URL and other request-related information. The  parameter will contain the response that resulted
        /// in the redirect. The  parameter will contain the new URL and can be changed if desired.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - cannot be modified in this callback.
        /// the response object - cannot be modified in this callback.
        /// [in,out] the new URL and can be changed if desired.
        void IResourceRequestHandler.OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl)
        {
            OnResourceRedirect(chromiumWebBrowser, browser, frame, request, response, ref newUrl);
        }

        /// 
        /// Called on the CEF IO thread when a resource load is redirected. The  parameter will contain the old
        /// URL and other request-related information. The  parameter will contain the response that resulted
        /// in the redirect. The  parameter will contain the new URL and can be changed if desired.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object - cannot be modified in this callback.
        /// the response object - cannot be modified in this callback.
        /// [in,out] the new URL and can be changed if desired.
        protected virtual void OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl)
        {

        }

        /// 
        /// 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  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.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object.
        /// the response object - cannot be modified in this callback.
        /// 
        /// To allow the resource load to proceed without modification return false. To redirect or retry the resource load optionally
        /// modify  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.
        /// 
        bool IResourceRequestHandler.OnResourceResponse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            return OnResourceResponse(chromiumWebBrowser, browser, frame, request, response);
        }

        /// 
        /// 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  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.
        /// 
        /// The ChromiumWebBrowser control.
        /// the browser object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the frame object - may be null if originating from ServiceWorker or CefURLRequest.
        /// the request object.
        /// the response object - cannot be modified in this callback.
        /// 
        /// To allow the resource load to proceed without modification return false. To redirect or retry the resource load optionally
        /// modify  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.
        /// 
        protected virtual bool OnResourceResponse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            return false;
        }

        /// 
        /// Called when the unamanged resource is freed.
        /// Unmanaged resources are ref counted and freed when
        /// the last reference is released, this works differently
        /// to .Net garbage collection.
        /// 
        protected virtual void Dispose()
        {

        }

        void IDisposable.Dispose()
        {
            Dispose();
        }
    }

2、要从Resource Filter中获取数据,先添加两个类FilterManager、TestJsonFilter,合并在一个文件FilterManager中,用来获取数据

public class TestJsonFilter : IResponseFilter
    {
        public List DataAll = new List();

        public FilterStatus Filter(System.IO.Stream dataIn, out long dataInRead, System.IO.Stream dataOut, out long dataOutWritten)
        {
            try
            {
                if (dataIn == null || dataIn.Length == 0)
                {
                    dataInRead = 0;
                    dataOutWritten = 0;

                    return FilterStatus.Done;
                }

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

                dataIn.CopyTo(dataOut);
                dataIn.Seek(0, SeekOrigin.Begin);
                byte[] bs = new byte[dataIn.Length];
                dataIn.Read(bs, 0, bs.Length);
                DataAll.AddRange(bs);

                dataInRead = dataIn.Length;
                dataOutWritten = dataIn.Length;

                return FilterStatus.NeedMoreData;
            }
            catch (Exception ex)
            {
                dataInRead = dataIn.Length;
                dataOutWritten = dataIn.Length;

                return FilterStatus.Done;
            }
        }

        public bool InitFilter()
        {
            return true;
        }

        public void Dispose()
        {

        }
    }
    public class FilterManager
    {
        private static Dictionary dataList = new Dictionary();

        public static IResponseFilter CreateFilter(string guid)
        {
            lock (dataList)
            {
                var filter = new TestJsonFilter();
                dataList.Add(guid, filter);

                return filter;
            }
        }

        public static IResponseFilter GetFileter(string guid)
        {
            lock (dataList)
            {
                return dataList[guid];
            }
        }
    }

3、新建类WinFormResourceRequestHandler,继承ResourceRequestHandler类,重写覆盖父类方法GetResourceResponseFilter、OnResourceLoadComplete

 public class WinFormResourceRequestHandler : ResourceRequestHandler
    {
        protected override IResponseFilter GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            var filter = FilterManager.CreateFilter(request.Identifier.ToString());
            return filter;
        }

        protected override void OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        {
            if (request.Url.ToLower().Contains("login".ToLower()))
            {
                var filter = FilterManager.GetFileter(request.Identifier.ToString()) as TestJsonFilter;
                ASCIIEncoding encoding = new ASCIIEncoding();
                //这里截获返回的数据
                var data = encoding.GetString(filter.DataAll.ToArray());
            }
        }
    }

此处也只拦截login登录返回的数据。也可以匹配别的页面请求

4、要修改IRequestHandler的实现类WinFormsRequestHandler中GetResourceRequestHandler方法,return null,改为return WinFormResourceRequestHandler,来调用请求后资源加载前的处理方法。

public class WinFormsRequestHandler : RequestHandler
    {
        protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
        {
            //NOTE: In most cases you examine the request.Url and only handle requests you are interested in
            if (request.Url.ToLower().Contains("login".ToLower()))
            {
                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);
                            }
                        }
                    }
                }
            }
            return new  WinFormResourceRequestHandler();
        }

    }

5、此时就可以调试运行,拦截获取到login请求后的的数据