是否可以将身份validation从Webbrowser传输到WebRequest
我使用webbrowser控件来login任何网站。 然后我想使用WebRequest(或WebClient)下载一些子页面的HTML。 这个链接必须要求authentication。
如何将Web浏览器身份validation信息传输到Webrequest或Webclient?
如果问题只是“如何将Web浏览器身份validation信息传输到Webrequest或Webclient?” 这个代码就够了:
您可以调用GetUriCookieContainer方法,该方法返回一个CookieContainer,可用于随后使用WebRequest对象进行调用。
[DllImport("wininet.dll", SetLastError = true)] public static extern bool InternetGetCookieEx( string url, string cookieName, StringBuilder cookieData, ref int size, Int32 dwFlags, IntPtr lpReserved); private const Int32 InternetCookieHttponly = 0x2000; /// <summary> /// Gets the URI cookie container. /// </summary> /// <param name="uri">The URI.</param> /// <returns></returns> public static CookieContainer GetUriCookieContainer(Uri uri) { CookieContainer cookies = null; // Determine the size of the cookie int datasize = 8192 * 16; StringBuilder cookieData = new StringBuilder(datasize); if (!InternetGetCookieEx(uri.ToString(), null, cookieData, ref datasize, InternetCookieHttponly, IntPtr.Zero)) { if (datasize < 0) return null; // Allocate stringbuilder large enough to hold the cookie cookieData = new StringBuilder(datasize); if (!InternetGetCookieEx( uri.ToString(), null, cookieData, ref datasize, InternetCookieHttponly, IntPtr.Zero)) return null; } if (cookieData.Length > 0) { cookies = new CookieContainer(); cookies.SetCookies(uri, cookieData.ToString().Replace(';', ',')); } return cookies; }
如果find这个解决scheme 用下面的信息简单地创build一个Class.cs文件,并调用静态的GetCookieInternal
函数。
using System; using System.ComponentModel; using System.Net; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Windows.Forms; internal sealed class NativeMethods { #region enums public enum ErrorFlags { ERROR_INSUFFICIENT_BUFFER = 122, ERROR_INVALID_PARAMETER = 87, ERROR_NO_MORE_ITEMS = 259 } public enum InternetFlags { INTERNET_COOKIE_HTTPONLY = 8192, //Requires IE 8 or higher INTERNET_COOKIE_THIRD_PARTY = 131072, INTERNET_FLAG_RESTRICTED_ZONE = 16 } #endregion #region DLL Imports [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("wininet.dll", EntryPoint = "InternetGetCookieExW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] internal static extern bool InternetGetCookieEx([In] string Url, [In] string cookieName, [Out] StringBuilder cookieData, [In, Out] ref uint pchCookieData, uint flags, IntPtr reserved); #endregion } /// <SUMMARY></SUMMARY> /// WebBrowserCookie? /// webBrowser1.Document.CookieHttpOnlyCookie /// public class FullWebBrowserCookie : WebBrowser { [SecurityCritical] public static string GetCookieInternal(Uri uri, bool throwIfNoCookie) { uint pchCookieData = 0; string url = UriToString(uri); uint flag = (uint)NativeMethods.InternetFlags.INTERNET_COOKIE_HTTPONLY; //Gets the size of the string builder if (NativeMethods.InternetGetCookieEx(url, null, null, ref pchCookieData, flag, IntPtr.Zero)) { pchCookieData++; StringBuilder cookieData = new StringBuilder((int)pchCookieData); //Read the cookie if (NativeMethods.InternetGetCookieEx(url, null, cookieData, ref pchCookieData, flag, IntPtr.Zero)) { DemandWebPermission(uri); return cookieData.ToString(); } } int lastErrorCode = Marshal.GetLastWin32Error(); if (throwIfNoCookie || (lastErrorCode != (int)NativeMethods.ErrorFlags.ERROR_NO_MORE_ITEMS)) { throw new Win32Exception(lastErrorCode); } return null; } private static void DemandWebPermission(Uri uri) { string uriString = UriToString(uri); if (uri.IsFile) { string localPath = uri.LocalPath; new FileIOPermission(FileIOPermissionAccess.Read, localPath).Demand(); } else { new WebPermission(NetworkAccess.Connect, uriString).Demand(); } } private static string UriToString(Uri uri) { if (uri == null) { throw new ArgumentNullException("uri"); } UriComponents components = (uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString); return new StringBuilder(uri.GetComponents(components, UriFormat.SafeUnescaped), 2083).ToString(); } }
样品:
var cookies = FullWebBrowserCookie.GetCookieInternal(webBrowser1.Url, false); WebClient wc = new WebClient(); wc.Headers.Add("Cookie: " + cookies); wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); byte[] result = wc.UploadData("<URL>", "POST", System.Text.Encoding.UTF8.GetBytes(postData));
你应该可以通过.Document.Cookie
访问WebBrowser
控件的cookie,然后在你的HTTPWebRequest
中添加这个cookie到它的cookie容器。
这里是一个例子(因为我最熟悉的VB.NET):
Dim browser As New WebBrowser() /*Do stuff here to auth with your webbrowser and get a cookie.*/ Dim myURL As String = "http://theUrlIWant.com/" Dim request As New HTTPWebRequest(myURL) request.CookieContainer = New CookieContainer() request.CookieContainer.SetCookies(myURL, browser.Document.Cookie)
这应该从您的WebBrowser
控制转移到您的HTTPWebRequest
类的cookie。
一种可能的方法是使用InternetGetCookie函数获取cookie,构造相应的cookie
对象并将其用于CookieContainer
要检索HttpOnly Cookie,请使用InternetGetCookieEx
这里有些例子:
.NET中的InternetGetCookie()
使用Internet Explorer Cookies下载
如果您可以在WebBrowser控件所设置的WebBrowser控件中检索必要的cookie,那么您应该可以在WebRequest / WebClient中使用这些cookie。
本文概述了如何在WebClient上使用cookie; 你必须inheritance它,但它只是一个需要的覆盖。
迟到的答案为未来的参考。 WebBrowser
使用UrlMon库来pipe理每个进程的会话,因此可以使用URLOpenStream或URLDownloadToFile等UrlMon API来下载同一会话中的任何资源(API可以通过P / invoke从C#中调用)。 类似的问题在这里回答。
我知道这是非常古老的问题,但有答案标记,所以我想分享我准备的解决scheme
我没有把我的cookies从webbrowser转移到webrequest,但是我使用了webclient来代替webrequest,为此我有下面的步骤
创buildCookie感知的Web客户端从Web浏览器控件parsingCookie将分析的Cookie分配给Cookie容器使用Cookie容器创buildCookie感知的Web客户端对象使用Cookie感知的Web客户端对象立即发送您的请求
在这个链接详细解释http://www.codewithasp.net/2016/06/transferring-cookies-webbrowser-webclient-c-net.html
要完成你正在做的事情并不容易。 服务器可以使用客户端(浏览器)
1)传输authentication2)基于表单的authentication
传输validation:在这种情况下,validation是通过传输连接本身来完成的 – 在这里它将使用自定义HTTP头与多路握手进行validation。
基于表单的身份validation:这是您将凭证input表单时完成的传统身份validation。
在任何一种情况下,身份validation都可能在您的托pipe控件实例化时已经发生。 正如有人build议,您可以窃取该域的浏览器cookie,并使用它与webclient,但它可能会或可能不会按照您的预期方式。
如果所有你想要做的是下载的东西,那么我会看看,如果我可以使用浏览器设施,例如XmlHttpRequest或一些其他的Ajax机制下载你想要的东西作为托pipe控制页面的DOM的一部分。 然后,您可以从您的控件中读取内容,或者也可以让浏览器通过调用控件上的方法/属性的方式将该内容注入到控件中。
[编辑]
找出(在Firefox中使用Firebug插件)到底如何在浏览器中完成基于表单的身份validation。 然后,您可以编写代码来完成与浏览器完全相同的请求/响应。 对于网站来说,客户端将像任何其他基于浏览器的客户端一样出现。 那么你应该能够从网站上下载任何你想要的东西。
希望这可以帮助。
我已经在Windows Mobile平台上实现了同样的问题,唯一有效的方法就是在发送请求之前,扩展WebBrowser控件(使用C ++:<)捕获POST / GETvariables。
这个图书馆可能会帮助你:
http://www.codeproject.com/KB/miscctrl/csEXWB.aspx
“这个库实现了Igor Tandetnik的PassthroughAPP包,它使得客户端能够拦截所有的HTTP和HTTPS请求和响应。”
因此,虽然不可能在标准WebBrowser控件上获得用于基本身份validation的POST / GETvariables,但如果使用扩展控件(例如链接的示例),则可能会发生这种情况 – 事实上,许多“Extended WebBrowser”控件都是由于与您非常相似的问题而创build。 不幸的是,据我所知,你需要使用非托pipe代码/ c ++ :(。