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 .
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.