问题
I am attempting to go to a HTTPS site from a WebBrowser Control in a Web Application, to get some basic information from the site (the site does not have a web service or any other API at this point) When I do this from IIS Express I am able to connect login and navigate to other pages just as I do when directly connecting from the web browser on that system everything works fine.
From most Development systems i.e. Windows 10 or Windows Server 2016 I can publish the web application, connect to the web application and then through the web application connect to the site, login and load other pages everything works fine. BUT…. When I deploy to GoDaddy and connect to the site through the application I am able to log in successfully but when I navigate to another page I am redirected to the login page.
I have noticed that I do not get back any JSESSION Cookies when going through the application on GoDaddy but I do get them in all of the other successful cases. I receive the JSESSON Cookies before I log in at the target site: http://www.altavista.com/ but any website that returns cookies on connect should suffice. I have changed the user agent to the same agent I have on the desktop and connected and still get the same results on GoDaddy.
I have tried this on GoDaddy sites that are SSL protected (HTTPS) and those that are not Just (HTTP). Hopefully someone has run into this type of problem before using the WebBrowser Control?
Here’s a test snippet of the code (As you might note I have tried lots of things to figure this out CookiePresistance, Clearing Cookies, JScript to clear the status etc.:
public static class NativeMethods
{
[DllImport("wininet.dll", SetLastError = true)]
private static extern bool InternetSetOption(IntPtr hInternet, int dwOption,
IntPtr lpBuffer, int lpdwBufferLength);
public static void SuppressCookiePersist()
{
int dwOption = 81; //INTERNET_OPTION_SUPPRESS_BEHAVIOR
int option = 3; // INTERNET_SUPPRESS_COOKIE_PERSIST
IntPtr optionPtr = Marshal.AllocHGlobal(sizeof(int));
Marshal.WriteInt32(optionPtr, option);
bool x = InternetSetOption(IntPtr.Zero, dwOption, optionPtr, sizeof(int));
Marshal.FreeHGlobal(optionPtr);
}
public static void EnableCookiePersist()
{
int dwOption = 81; //INTERNET_OPTION_SUPPRESS_BEHAVIOR
int option = 4; // INTERNET_SUPPRESS_COOKIE_POLICY ignores policy and allows cookies to be set https://msdn.microsoft.com/en-us/library/windows/desktop/aa385328(v=vs.85).aspx
IntPtr optionPtr = Marshal.AllocHGlobal(sizeof(int));
Marshal.WriteInt32(optionPtr, option);
InternetSetOption(IntPtr.Zero, dwOption, optionPtr, sizeof(int));
option = 1;
Marshal.WriteInt32(optionPtr, option);
InternetSetOption(IntPtr.Zero, dwOption, optionPtr, sizeof(int));
Marshal.FreeHGlobal(optionPtr);
}
public static void ClearBrowserSession()
{
int dwOption = 42; //INTERNET_OPTION_END_BROWSER_SESSION
InternetSetOption(IntPtr.Zero, dwOption, IntPtr.Zero, 0);
}
}
public partial class TestStub: System.Web.UI.Page
{
protected void btnNavigate_Click(object sender, EventArgs e)
{
NativeMethods.EnableCookiePersist();
if(tbUrl.Text == "")
{
Client_Alert("Please enter url");
return;
}
if (tbUserAgent.Text == "")
tbUserAgent.Text = CurrentUserAgent;
object o = tbUrl.Text;
var t = new Thread((ParameterizedThreadStart)GetPage);
t.SetApartmentState(ApartmentState.STA);
t.Start(o);
GettingPage = true;
while (GettingPage == true)
Thread.Sleep(500);
t.Join();
return;
}
private void GetPage(object o)
{
StringBuilder SB = new StringBuilder();
DirectorBrowser = new WebBrowser();
NativeMethods.ClearBrowserSession();
DirectorBrowser.ScrollBarsEnabled = false;
DirectorBrowser.ScriptErrorsSuppressed = true;
DirectorBrowser.AllowNavigation = true;
DirectorBrowser.Navigate("javascript:void((function(){var a,b,c,e,f;f=0;a=document.cookie.split('; '); for (e = 0; e < a.length && a[e]; e++) { f++; for (b = '.' + location.host; b; b = b.replace(/^ (?:% 5C.|[^% 5C.] +) /, '')){ for (c = location.pathname; c; c = c.replace(/.$/, '')) { document.cookie = (a[e] + '; domain=' + b + '; path=' + c + '; expires=' + new Date((new Date()).getTime() - 1e11).toGMTString()); } }}})())");
NativeMethods.EnableCookiePersist();
DirectorBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_NoticeCompleted);
Uri url = new Uri((string)o);
DirectorBrowser.Navigate(url, null, null, "User-Agent: " + tbUserAgent.Text);
GettingPage = true;
while (GettingPage == true)
{
System.Windows.Forms.Application.DoEvents();
Thread.Sleep(500);
}
}
private void browser_NoticeCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (GettingPage == true)
{
HtmlElement body = DirectorBrowser.Document.Body;
HtmlElementCollection inputs = DirectorBrowser.Document.GetElementsByTagName("INPUT");
HtmlElementCollection forms = DirectorBrowser.Document.Forms;
body = DirectorBrowser.Document.Body;
string webResults = body.InnerHtml;
HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
htmlDoc.LoadHtml(webResults);
htmlDoc.OptionFixNestedTags = true;
tbMaintenanceResults.Text = "Cookies: <br>" + DirectorBrowser.Document.Cookie + "<br>" + body.InnerHtml;
GettingPage = false;
}
else
{
GettingPage = false;
}
}
}
回答1:
After adding a custom Security Manager, and still not having success:
public partial class InternetSecurityManager : IInternetSecurityManager
{
private static Guid _CLSID_SecurityManager = new Guid("7b8a2d94-0ac9-11d1-896c-00c04fb6bfc4");
private static string[] ZoneNames = new[] { "Local", "Intranet", "Trusted", "Internet", "Restricted" };public static string GetUrlZone(string url)
{
Type t = System.Type.GetTypeFromCLSID(_CLSID_SecurityManager);
IInternetSecurityManager securityManager = (IInternetSecurityManager)System.Activator.CreateInstance(t);
try
{
uint zone = 0;
int hResult = securityManager.MapUrlToZone(url, ref zone, 0);
if (hResult != 0)
throw new COMException("Error calling MapUrlToZone, HRESULT = " + hResult.ToString("x"), hResult);
if (zone < ZoneNames.Length)
return ZoneNames[zone];
return "Unknown - " + zone;
}
finally
{
Marshal.ReleaseComObject(securityManager);
}
}
public static void GetUrlZoneCookiesPermissions(string url)
{
Type t = System.Type.GetTypeFromCLSID(_CLSID_SecurityManager);
IInternetSecurityManager securityManager = (IInternetSecurityManager)System.Activator.CreateInstance(t);
try
{
uint puaf = 0x00000040; //PUAF TRUSTED
byte obptr = 0;
int hResult = securityManager.ProcessUrlAction(url, 0x00001A06, out obptr, 1, 0, 0, puaf, 0);
//hResult = securityManager.ProcessUrlAction(url, 0x00001A10, out obptr, 1, 0, 0, puaf, 0);
hResult = securityManager.ProcessUrlAction(url, 0x00001A03, out obptr, 1, 0, 0, puaf, 0);
return;
}
finally
{
Marshal.ReleaseComObject(securityManager);
}
}
[return: MarshalAs(UnmanagedType.I4)]
public int SetSecuritySite([In] IntPtr pSite)
{
return Convert.ToInt32( 0x800C0011); //INET_E_DEFAULT_ACTION;
}
[return: MarshalAs(UnmanagedType.I4)]
public int GetSecuritySite([Out] IntPtr pSite)
{
return Convert.ToInt32(0x800C0011); //INET_E_DEFAULT_ACTION;
}
[return: MarshalAs(UnmanagedType.I4)]
public int MapUrlToZone([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, ref uint pdwZone, uint dwFlags)
{
return Convert.ToInt32(0x800C0011); //INET_E_DEFAULT_ACTION;
}
[return: MarshalAs(UnmanagedType.I4)]
public int GetSecurityId([MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSecurityId, ref uint pcbSecurityId, uint dwReserved)
{
return Convert.ToInt32(0x800C0011); //INET_E_DEFAULT_ACTION;
}
[return: MarshalAs(UnmanagedType.I4)]
public int ProcessUrlAction([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, uint dwAction, out byte pPolicy, uint cbPolicy, byte pContext, uint cbContext, uint dwFlags, uint dwReserved)
{
pPolicy = 0;
return 0;// S_OK;
}
[return: MarshalAs(UnmanagedType.I4)]
public int QueryCustomPolicy([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, ref Guid guidKey, ref byte ppPolicy, ref uint pcbPolicy, ref byte pContext, uint cbContext, uint dwReserved)
{
return Convert.ToInt32(0x800C0011); //INET_E_DEFAULT_ACTION;
}
[return: MarshalAs(UnmanagedType.I4)]
public int SetZoneMapping(uint dwZone, [In, MarshalAs(UnmanagedType.LPWStr)] string lpszPattern, uint dwFlags)
{
return Convert.ToInt32(0x800C0011); //INET_E_DEFAULT_ACTION;
}
[return: MarshalAs(UnmanagedType.I4)]
public int GetZoneMappings(uint dwZone, out UCOMIEnumString ppenumString, uint dwFlags)
{
ppenumString = null;
return Convert.ToInt32(0x800C0011); //INET_E_DEFAULT_ACTION;
}
}
[ComImport, GuidAttribute("79EAC9EE-BAF9-11CE-8C82-00AA004BA90B")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInternetSecurityManager
{
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int SetSecuritySite([In] IntPtr pSite);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetSecuritySite([Out] IntPtr pSite);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int MapUrlToZone([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl,
ref UInt32 pdwZone, UInt32 dwFlags);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetSecurityId([MarshalAs(UnmanagedType.LPWStr)] string pwszUrl,
[MarshalAs(UnmanagedType.LPArray)] byte[] pbSecurityId,
ref UInt32 pcbSecurityId, uint dwReserved);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int ProcessUrlAction([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl,
UInt32 dwAction, out byte pPolicy, UInt32 cbPolicy,
byte pContext, UInt32 cbContext, UInt32 dwFlags,
UInt32 dwReserved);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int QueryCustomPolicy([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl,
ref Guid guidKey, ref byte ppPolicy, ref UInt32 pcbPolicy,
ref byte pContext, UInt32 cbContext, UInt32 dwReserved);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int SetZoneMapping(UInt32 dwZone,
[In, MarshalAs(UnmanagedType.LPWStr)] string lpszPattern,
UInt32 dwFlags);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int GetZoneMappings(UInt32 dwZone, out UCOMIEnumString ppenumString,
UInt32 dwFlags);
}
}
I found this post from 2006: http://www.tech-archive.net/Archive/InetSDK/microsoft.public.inetsdk.programming.webbrowser_ctl/2006-03/msg00073.html Apparently Cookies are not handled by the Security Manager they are handled by the Zone manager which cannot be customized. The only way to fix this is to add an additional zone for your specific needs to the registry. Unfortunately there is no way to do this from code when you are using the WebBrowser Control. And if your Site is Hosted in a Web Farm you don't have access to the registry so another approach will be needed (possibly a IE Plug In or deploy on a server where you have access and permission to set the default browser to what you need)
来源:https://stackoverflow.com/questions/45678518/webbrowser-control-in-web-server-not-returning-cookie-from-website