简体   繁体   中英

Implement custom 401 handling for a WebBrowser control

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.

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 .

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());
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM