Winforms,CefSharp : Authentication popup for basic authentication not show

会有一股神秘感。 提交于 2020-12-06 17:39:19

问题


I am working on adding cefsharp in a WinForms application. Our website uses basic authentication for access, but CefSharp wont show that popup. I found out this and this, but Visual studio doesn't implement the interface and complains about AuthDialog being an unknown class. I come from Java side, not much idea about classes in Winforms, but I cant find AuthDialog. What am I doing wrong?

Code :

 bool IRequestHandler.GetAuthCredentials(IWebBrowser browser, bool isProxy, string host, int port,
            string realm, string scheme, ref string username, ref string password)
        {
            //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.

            // shyam - original implemenation.
            //callback.Dispose();
            //return false;

            bool handled = false;

            // Instantiate the dialog box

            AuthDialog dlg = new AuthDialog(host); // create new dialog with username and password field.

            // Open the dialog box modally 
            dlg.ShowDialog();

            if (dlg.DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                // The user did not cancel out of the dialog. Retrieve the username and password.
                callback.Continue(dlg.UserName, dlg.Password);
                handled = true;
            }

            return handled;
        }

Screenshots :


回答1:


The solution which worked for me :

public class MyRequestHandler : IRequestHandler
    {
        private string userName;
        private string password;

        public MyRequestHandler(string userName, string password)
        {
            this.userName = userName;
            this.password = password;
        }


        //public static readonly string VersionNumberString = String.Format("Chromium: {0}, CEF: {1}, CefSharp: {2}",
        //   Cef.ChromiumVersion, Cef.CefVersion, Cef.CefSharpVersion);

        bool IRequestHandler.OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect)
        {
            return false;
        }

        bool IRequestHandler.OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
        {
            return OnOpenUrlFromTab(browserControl, browser, frame, targetUrl, targetDisposition, userGesture);
        }

        protected virtual bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
        {
            return false;
        }

        bool IRequestHandler.OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, 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)
            //    {
            //        //To allow certificate
            //        //callback.Continue(true);
            //        //return true;
            //    }
            //}

            return false;
        }

        void IRequestHandler.OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath)
        {
            // TODO: Add your own code here for handling scenarios where a plugin crashed, for one reason or another.
        }

        CefReturnValue IRequestHandler.OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
        {
            //Example of how to set Referer
            // Same should work when setting any header

            // For this example only set Referer when using our custom scheme
            //var url = new Uri(request.Url);
            //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;
        }

        bool IRequestHandler.GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback 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.Continue(userName, password);           

            return true;
        }

        void IRequestHandler.OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status)
        {
            // TODO: Add your own code here for handling scenarios where the Render Process terminated for one reason or another.
            //  browserControl.Load(CefExample.RenderProcessCrashedUrl);
        }

        bool IRequestHandler.OnQuotaRequest(IWebBrowser browserControl, 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;
        }


        bool IRequestHandler.OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url)
        {
            return url.StartsWith("mailto");
        }

        void IRequestHandler.OnRenderViewReady(IWebBrowser browserControl, IBrowser browser)
        {

        }

        bool IRequestHandler.OnResourceResponse(IWebBrowser browserControl, 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.ResponseHeaders;

            return false;
        }

        IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            //var url = new Uri(request.Url);
            //if (url.Scheme == CefSharpSchemeHandlerFactory.SchemeName)
            //{
            //    if (request.Url.Equals(CefExample.ResponseFilterTestUrl, StringComparison.OrdinalIgnoreCase))
            //    {
            //        return new FindReplaceResponseFilter("REPLACE_THIS_STRING", "This is the replaced string!");
            //    }

            //    if (request.Url.Equals("custom://cefsharp/assets/js/jquery.js", StringComparison.OrdinalIgnoreCase))
            //    {
            //        return new AppendResponseFilter(System.Environment.NewLine + "//CefSharp Appended this comment.");
            //    }

            //    return new PassThruResponseFilter();
            //}

            return null;
        }

        void IRequestHandler.OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        {

        }

        public bool OnSelectClientCertificate(IWebBrowser browserControl, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback)
        {
            return false;
        }

        public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl)
        {

        }
    }

and call it in chromium browser call it like this :

 private void InitializeChromium()
        {
            chromiumBrowser = new ChromiumWebBrowser("https://www.google.com")
            {
                Dock = DockStyle.Fill,
            };
            chromiumBrowser.RequestHandler = new MyRequestHandler("actual_username","actual_password");

            this.Controls.Add(chromiumBrowser);
        }



回答2:


You will need to add reference to CefSharp through nuget packager. You can open nuget package console from Tools -> Nuget package manger. Then run this command:

Install-Package CefSharp.WinForms -Version 63.0.3

Once you have added that, you will be able to access relevant classes.

For AuthDialog, I assume you have a form created somewhere in the application. The namespace for that needs to be added. If there is no such form, you will need to create one where user can give username and password.




回答3:


The following solution worked for me. I created a new class which inherits the RequestHandler class and added a custom dialog to enter the user credentials. if the entered details don't have permission/authorization, the popup will show invalid credentials.

   public class MyRequestHandler : RequestHandler
{
    private string userName;
    private string password;
    private string ValidationMessage = string.Empty;
    protected override bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
    {
        userName = Environment.UserDomainName + @"\" + Environment.UserName;
        if (!Getcredentials(ref userName, ref password))
        {

            AllowCredentials dlg = new AllowCredentials();
            dlg.Topmost = true;
            dlg.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
            dlg.textBlock.Text = userName;
            dlg.InvalidCredentials.Content = ValidationMessage;
            dlg.ShowDialog();
            if (dlg.SetCredentials == true)
            {
                password = dlg.txtPassword.Password;
                //to check if the site is accessible with the login credentials
                if (IsCredentialsValid(userName, password, originUrl))
                {
                    callback.Continue(userName, password);
                    SaveWindowsCredentials(userName, password);
                    ValidationMessage = string.Empty;
                }
                else { ValidationMessage = "Invalid Credentials"; callback.Continue(string.Empty, string.Empty); }
            }
            else
            {
                return false;
            }
        }
        else
        {
            if (IsCredentialsValid(userName, password, originUrl))
            {
                callback.Continue(userName, password);
            }
            else { ValidationMessage = "Invalid Credentials"; callback.Continue(string.Empty, string.Empty); }
        }

        return true;
    }

    private void SaveWindowsCredentials(string UserName, string Password)
    {
        try
        {
            using (Credential cred = new Credential())
            {
                cred.Password = password;
                cred.Target = UserName;
                cred.Username = UserName;
                cred.Type = CredentialType.Generic;
                cred.PersistanceType = PersistanceType.Enterprise;
                cred.Save();
            }
        }
        catch (System.Exception)
        {

            throw;
        }
    }

    private bool Getcredentials(ref string UserName, ref string Password)
    {
        try
        {
            using (Credential cred = new Credential())
            {
                cred.Target = UserName;
                cred.Username = UserName;
                cred.Load();
                Password = cred.Password;
            }
            if (string.IsNullOrEmpty(Password)) { return false; }
            else
            {
                return true;
            }
        }
        catch (System.Exception)
        {

            throw;
        }
    }

    private bool IsCredentialsValid(string UserName, string Password, string URL)
    {
        try
        {
            var request = WebRequest.Create(URL);
            request.Credentials = new System.Net.NetworkCredential(UserName, Password);
            var response = request.GetResponse();
            if (response.IsMutuallyAuthenticated) { return true; }
            else
            {
                return false;
            }
        }
        catch (Exception)
        {
            return false;
        }
    }
}


来源:https://stackoverflow.com/questions/49667634/winforms-cefsharp-authentication-popup-for-basic-authentication-not-show

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!