为 WebBrowser 控件实现自定义 401 处理

发布于 2024-12-15 08:40:12 字数 1008 浏览 5 评论 0原文

根据这篇文章,我'我们扩展了 System.Windows.Forms.WebBrowser 类来实现自定义错误处理。大多数情况下,它有效。

当浏览器收到“401 Unauthorized”响应时,问题就出现了。这种响应会导致 WebBrowser 控件显示标准的用户名/密码对话框。在取消该对话框之前,不会触发 NavigateError 事件。

那么我该怎么做才能捕获 401 响应并以我自己的自定义方式处理它呢?

我以为我可以做一些事情,例如捕获 NavigateError 事件,并以我自己的方式处理这些事件,但我没有看到任何东西。

编辑:找到解决方案!
重要步骤是:
1. WebBrowser 控件必须首先导航到非安全页面(“about:blank”是使用的典型 URL)以避免知识库 320153
2. WebBrowser 控件的宿主必须实现 IOleClientSiteIServiceProviderIAuthenticate
3. IServiceProvider.QueryService 必须使用 IAuthenticate 实现处理 IAuthenticate 服务请求,所有其他服务请求都可以使用 INET_E_DEFAULT_ACTION 处理 响应。
4. IAuthenticate.Authenticate 是您的自定义身份验证处理程序。

As per this article, I've extended the System.Windows.Forms.WebBrowser class to implement custom error-handling. Mostly, it works.

The problem comes when the browser gets a "401 Unauthorized" response. That kind of response causes the WebBrowser control to display the standard Username / Password dialog. The NavigateError event isn't fired until that dialog is cancelled.

So what can I do to capture the 401 response and handle it in my own custom way?

I assumed there would be something I could do, such as that which I do to capture the NavigateError event, and handle those my own way but I haven't seen anything.

Edit: Solution Found!
The important steps are:
1. The WebBrowser control must first be navigated to a non-secure page ("about:blank" is the typical URL used) in order to avoid KB 320153
2. The host for the WebBrowser control must implement IOleClientSite, IServiceProvider, and IAuthenticate.
3. IServiceProvider.QueryService must handle the IAuthenticate service request with the IAuthenticate implementation, all other service requests can be handled with the INET_E_DEFAULT_ACTION response.
4. IAuthenticate.Authenticate is your custom authentication handler.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

护你周全 2024-12-22 08:40:12

实施您的网络浏览器主机上的 IAuthenticate 和 IAuthenticateEx。基本上,您的 IOleClientSite 实现需要响应 IServiceProvider.QueryService,并在服务为 IID_IAuthenticate 时返回 IAuthenticate(Ex) 接口(不是托管接口,而是从 Marshal.GetComInterfaceForObject 返回的本机接口)。对于无法识别的服务请求,QueryService 应返回 INET_E_DEFAULT_ACTION。

我认为 WPF Web 浏览器没有其 IOleClientSite 实现的扩展点。您可以尝试托管一个 Winform webbrowser 类,该类具有重写的 CreateWebBrowserSiteBase 虚拟方法,该方法提供 IAuthenticate(Ex) 实现,或 从头开始编写一个网络浏览器包装器

这可能不适用于 Citrix会话

implement IAuthenticate and IAuthenticateEx on your webbrowser host. Basically, your IOleClientSite implementation needs to responde IServiceProvider.QueryService, and return an IAuthenticate(Ex) interface (not the managed one, the native one returned from Marshal.GetComInterfaceForObject) when the service is IID_IAuthenticate. For unrecognized service requests, QueryService should return INET_E_DEFAULT_ACTION.

I don't think the WPF webbrowser has extension points for its IOleClientSite implementation. You can try host a Winform webbrowser class which has an overriden CreateWebBrowserSiteBase virtual method that provides the IAuthenticate(Ex) implementation, or write a webbrowser wrapper from the ground up.

This may not work in a Citrix session.

吖咩 2024-12-22 08:40:12

我发现为了能够在授权标头不丢失或删除的情况下导航网站,我必须执行以下操作,否则对于每个新页面都会再次提示用户。此解决方案也不需要启用 user:password@site 语法。

    private bool _redirected = false;
    private const string BaseUrl = @"http://mySite";

    private void Navigate()
    {
        var helpUrl = BaseUrl;
        var authHeader = GetAuthHeader();

        _docWindow.Browser.Navigate(helpUrl, string.Empty, null, authHeader);           
        _docWindow.Browser.Navigating += Browser_Navigating;

    }

    private string GetAuthHeader()
    {
        byte[] authData = UnicodeEncoding.UTF8.GetBytes(_userName + ":" + _password);
        string authHeader = "Authorization: Basic " + Convert.ToBase64String(authData);
        return authHeader;
    }

    void Browser_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
    {            
        if (_redirected)
        {
            _redirected = false;
            return;
        }
        var newPage = BaseUrl + e.Uri.AbsolutePath;

        e.Cancel = true;
        _redirected = true;
        _docWindow.Browser.Navigate(newPage, string.Empty, null, GetAuthHeader());
    }

I found that to be able to navigate the site without the Authorization Header getting lost or removed I had to do the following otherwise for each new page the user was prompted again. This solution also does not require the user:password@site syntax to be enabled.

    private bool _redirected = false;
    private const string BaseUrl = @"http://mySite";

    private void Navigate()
    {
        var helpUrl = BaseUrl;
        var authHeader = GetAuthHeader();

        _docWindow.Browser.Navigate(helpUrl, string.Empty, null, authHeader);           
        _docWindow.Browser.Navigating += Browser_Navigating;

    }

    private string GetAuthHeader()
    {
        byte[] authData = UnicodeEncoding.UTF8.GetBytes(_userName + ":" + _password);
        string authHeader = "Authorization: Basic " + Convert.ToBase64String(authData);
        return authHeader;
    }

    void Browser_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
    {            
        if (_redirected)
        {
            _redirected = false;
            return;
        }
        var newPage = BaseUrl + e.Uri.AbsolutePath;

        e.Cancel = true;
        _redirected = true;
        _docWindow.Browser.Navigate(newPage, string.Empty, null, GetAuthHeader());
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文