在使用CefSharp处理身份验证请求时,如何在关闭时修复无限对话循环

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在使用CefSharp处理身份验证请求时,如何在关闭时修复无限对话循环相关的知识,希望对你有一定的参考价值。

因此,我正在制作的应用程序需要处理网页发送的身份验证请求,以便登录并使用该页面。为了实现这一点,我在一些研究后发现,我应该实现CefSharp的IRequestHandler接口,并使用名为“GetAuthCredentials”的方法打开一个对话框,并从这里请求用户名和密码。

这一切似乎工作正常,我能够使用正确的凭据登录到页面。但是,当我尝试通过此方法登录网站后关闭我的整个应用程序时,应用程序冻结并拒绝关闭。它似乎关闭了窗体上的浏览器控件,但不关闭窗体本身。

当我不必使用登录时,我可以正常关闭应用程序而没有任何问题,但每当我执行上述场景时,除了在Taskmanager中结束任务之外我无法关闭它。

我怀疑“GetAuthCredentials”从未真正处理过,或者一直反复请求对话,导致无限循环使我的应用程序无法关闭。但是我无法找到这个问题的根源。

使用“GetAuthCredentials”的Requesthandler实现:

class RequestEventHandler : IRequestHandler
    {

        bool IRequestHandler.GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
        {
            bool handled = false;

            AuthenticationDialog dlg = new AuthenticationDialog(host);

            dlg.ShowDialog();

            if (dlg.DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                callback.Continue(dlg.UserName, dlg.Password);
                handled = true;
            }

            return handled;
        }

它打开的Dialogform:

 public partial class AuthenticationDialog : Form
    {
        internal string UserName { get; set; }
        internal string Password { get; set; }

        public AuthenticationDialog(string Hostname)
        {
            InitializeComponent();
            Lbl_WebUrl.Text = Hostname;

        }

        private void Btn_SignIn_Click(object sender, EventArgs e)
        {
            if(Tbx_Username.TextLength > 0 && Tbx_Password.TextLength > 0)
            {
                UserName = Tbx_Username.Text;
                Password = Tbx_Password.Text;
            }
            else if (Tbx_Username.TextLength == 0 && Tbx_Password.TextLength > 0)
            {
                Lbl_Error.Text = SetError(1);
            }
            else if (Tbx_Username.TextLength > 0 && Tbx_Password.TextLength == 0)
            {
                Lbl_Error.Text = SetError(2);
            }
            else
            {
                Lbl_Error.Text = SetError(0);
            }
        }

此处的登录按钮将Dialog_Result属性设置为Dialogresult.OK

关闭应用程序的方法:(位于包含浏览​​器的mainform中)

private void btn_ApplicationClose_Click(object sender, EventArgs e)
        {
            browser.Dispose();
            Cef.Shutdown();
            Application.Exit();
        }

任何关于这个问题的建议或解决方案都会非常感激,这个问题已经磨了几天了。

更新:根据@amaitland的建议,我使用以下代码在UI线程上打开了对话框:

bool IRequestHandler.GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
        {
            bool handled = false;

            ChromiumWebBrowser b = browserControl as ChromiumWebBrowser;
            b.BeginInvoke((MethodInvoker)delegate
            {
                AuthenticationDialog dlg = new AuthenticationDialog(host);
                dlg.ShowDialog();

                if (dlg.DialogResult == System.Windows.Forms.DialogResult.OK)
                {
                    callback.Continue(dlg.UserName, dlg.Password);
                    handled = true;
                }
            });

            return handled;

这似乎有效,让我的应用程序在使用登录时关闭,但是现在似乎无法处理登录信息。登录时,它关闭对话框,似乎没有对我给出的凭据做任何事情。

我错过了什么或者我的实施错了吗?

答案

因此,通过@amaitland的一些有用的建议,我已经能够解决我的问题,导致下面的代码用于RequestHandler的GetAuthCredentials方法。

bool IRequestHandler.GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
        {
            ChromiumWebBrowser b = browserControl as ChromiumWebBrowser; //casts the given browsercontrol as chromiumwebbrowser, to acces the .beginInvoke method
            b.BeginInvoke((MethodInvoker)delegate
            {
                //creates an instance of the authentication dialog to get the user credentials
                AuthenticationDialog dlg = new AuthenticationDialog(host);
                dlg.ShowDialog();


                if (dlg.DialogResult == System.Windows.Forms.DialogResult.OK)  //if the sign-in button is clicked
                {
                    callback.Continue(dlg.UserName, dlg.Password);
                }
                else // if the close or cancel button on field is clicked
                {
                    callback.Cancel();
                }
            });
            return true;
        }

在这里,我使用.BeginInvoke()在UI线程而不是主线程上打开对话框,并确保请求将在处理时使用处理。这解决了我使用它的所有问题,它可能会给出一个示例来实现您自己的RequestHandler for GetAuthCredentials

以上是关于在使用CefSharp处理身份验证请求时,如何在关闭时修复无限对话循环的主要内容,如果未能解决你的问题,请参考以下文章

如何在不丢失身份验证的情况下模拟Session.request?

在刷新身份验证令牌时处理多个未经授权的请求

尝试调用 AIA 时,Keycloak“处理对身份提供者的身份验证请求时出现意外错误”

Symfony3 +“由于系统原因无法处理身份验证请求”

Heroku节点+反应应用程序:未处理的锚标记身份验证请求

使用 React 处理 JWT 身份验证