CefSharp 3 set proxy at Runtime

后端 未结 4 1442
执念已碎
执念已碎 2020-12-10 17:09

I downloaded CEF (chromuim embedded framework) binary distributation that comes with (cefclient & cefsimple) c++ examples, And Realized that cefclient can change proxy s

相关标签:
4条回答
  • 2020-12-10 17:37

    If you want dynamic proxy resolver (proxy hanlder), which allow you to use different proxy for different host - you should:

    1) Prepare javascript

    var proxy1Str = "PROXY 1.2.3.4:5678";
    var proxy2Str = "PROXY 2.3.4.5:6789";
    
    var ProxyPacScript = 
        $"var proxy1 = \"{(proxy1Str.IsNullOrEmpty() ? "DIRECT" : proxy1Str)}\";" +
        $"var proxy2 = \"{(proxy2Str.IsNullOrEmpty() ? "DIRECT" : proxy2Str)}\";" +
    
        @"function FindProxyForURL(url, host) {
            if (shExpMatch(host, ""*example.com"")) {
                return proxy1;
            }
            return proxy2;
        }";
    
    var bytes = Encoding.UTF8.GetBytes(ProxyPacScript);
    var base64 = Convert.ToBase64String(bytes);
    

    2) Set it correctly

    var v = new Dictionary<string, object>();
    v["mode"] = "pac_script";
    v["pac_url"] = "data:application/x-ns-proxy-autoconfig;base64," + base64;
    

    3) Call SetPreference as in accepted answer https://stackoverflow.com/a/36106994/9252162

    As result all request to *example.com will flow throught proxy1, all others through proxy2.

    To do it I spent all day but with help of source (https://cs.chromium.org/) I found solution. Hope it helps someone.

    Main problems:

    1) In new version (72 or 74 as I remember) there is no ability to use "file://..." as pac_url.

    2) We can't use https://developer.chrome.com/extensions/proxy in cef.. or i can't find how to do it.

    p.s. How to use another types of proxy (https, socks) - https://chromium.googlesource.com/chromium/src/+/master/net/docs/proxy.md#evaluating-proxy-lists-proxy-fallback

    0 讨论(0)
  • 2020-12-10 17:55

    I downloaded CefSharp.WinForms 65.0.0 and made class, that can help to start working with proxy:

    public class ChromeTest
    {
        public static ChromiumWebBrowser Create(WebProxy proxy = null, Action<ChromiumWebBrowser> onInited = null)
        {
           var result = default(ChromiumWebBrowser);
            var settings = new CefSettings();
            result = new ChromiumWebBrowser("about:blank");
            if (proxy != null)
                result.RequestHandler = new _requestHandler(proxy?.Credentials as NetworkCredential);
    
            result.IsBrowserInitializedChanged += (s, e) =>
            {
                if (!e.IsBrowserInitialized)
                    return;
    
                var br = (ChromiumWebBrowser)s;
                if (proxy != null)
                {
                    var v = new Dictionary<string, object>
                    {
                        ["mode"] = "fixed_servers",
                        ["server"] = $"{proxy.Address.Scheme}://{proxy.Address.Host}:{proxy.Address.Port}"
                    };
                    if (!br.GetBrowser().GetHost().RequestContext.SetPreference("proxy", v, out string error))
                        MessageBox.Show(error);
                }
    
                onInited?.Invoke(br);
            };
    
            return result;
        }
    
        private class _requestHandler : DefaultRequestHandler
        {
            private NetworkCredential _credential;
    
            public _requestHandler(NetworkCredential credential = null) : base()
            {
                _credential = credential;
            }
    
            public override bool GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
            {
                if (isProxy == true)
                {
                    if (_credential == null)
                        throw new NullReferenceException("credential is null");
    
                    callback.Continue(_credential.UserName, _credential.Password);
                    return true;
                }
    
                return false;
            }
        }
    }
    

    Using:

            var p = new WebProxy("Scheme://Host:Port", true, new[] { "" }, new NetworkCredential("login", "pass"));
            var p1 = new WebProxy("Scheme://Host:Port", true, new[] { "" }, new NetworkCredential("login", "pass"));
            var p2 = new WebProxy("Scheme://Host:Port", true, new[] { "" }, new NetworkCredential("login", "pass"));
    
            wb1 = ChromeTest.Create(p1, b => b.Load("http://speed-tester.info/check_ip.php"));
            groupBox1.Controls.Add(wb1);
            wb1.Dock = DockStyle.Fill;
    
            wb2 = ChromeTest.Create(p2, b => b.Load("http://speed-tester.info/check_ip.php"));
            groupBox2.Controls.Add(wb2);
            wb2.Dock = DockStyle.Fill;
    
            wb3 = ChromeTest.Create(p, b => b.Load("http://speed-tester.info/check_ip.php"));
            groupBox3.Controls.Add(wb3);
            wb3.Dock = DockStyle.Fill;
    
    0 讨论(0)
  • 2020-12-10 17:56

    if anyone need any other soulition i found this solution.

    Cef.UIThreadTaskFactory.StartNew(delegate
            {
                string ip = "ip or adress";
                string port = "port";
                var rc = this.browser.GetBrowser().GetHost().RequestContext;
                var dict = new Dictionary<string, object>();
                dict.Add("mode", "fixed_servers");
                dict.Add("server", "" + ip + ":" + port + "");
                string error;
                bool success = rc.SetPreference("proxy", dict, out error);
    
            });
    
    0 讨论(0)
  • 2020-12-10 17:58

    thanks to amaitland the proper way to actively inforce changing the request-context prefrences, is to run the code on CEF UIThread as following:

        Cef.UIThreadTaskFactory.StartNew(delegate {
            var rc = this.browser.GetBrowser().GetHost().RequestContext;
            var v = new Dictionary<string, object>();
            v["mode"] = "fixed_servers";
            v["server"] = "scheme://host:port";
            string error;
            bool success = rc.SetPreference("proxy", v, out error);
            //success=true,error=""
        });
    
    0 讨论(0)
提交回复
热议问题