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

时间:2011-11-14 20:59:36

标签: c# webbrowser-control http-status-code-401

根据this article,我扩展了System.Windows.Forms.WebBrowser类以实现自定义错误处理。大多数情况下,它都有效。

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

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

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

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

2 个答案:

答案 0 :(得分:3)

implement IAuthenticate and IAuthenticateEx on your webbrowser host。基本上,您的IOleClientSite实现需要响应IServiceProvider.QueryService,并在服务为IID_IAuthenticate时返回IAuthenticate(Ex)接口(不是托管的接口,从Marshal.GetComInterfaceForObject返回的本机接口)。对于无法识别的服务请求,QueryService应返回INET_E_DEFAULT_ACTION。

我认为WPF webbrowser的IOleClientSite实现没有扩展点。您可以尝试托管一个Winform webbrowser类,该类具有覆盖CreateWebBrowserSiteBase虚拟方法,该方法提供IAuthenticate(Ex)实现,或write a webbrowser wrapper from the ground up

This may not work in a Citrix session

答案 1 :(得分:0)

我发现,为了能够在没有授权标题丢失或删除的情况下导航网站,我必须执行以下操作,否则每个新页面都会再次提示用户。此解决方案也不需要用户: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());
    }