我正在使用webbrowser控件登錄任何站點。然後我想使用WebRequest(或WebClient)下載一些子頁面的HTML。這個鏈接必須要求認證。是否可以將身份驗證從Webbrowser轉移到WebRequest
如何將Web瀏覽器身份驗證信息傳輸到Webrequest或Webclient?
我正在使用webbrowser控件登錄任何站點。然後我想使用WebRequest(或WebClient)下載一些子頁面的HTML。這個鏈接必須要求認證。是否可以將身份驗證從Webbrowser轉移到WebRequest
如何將Web瀏覽器身份驗證信息傳輸到Webrequest或Webclient?
如果您可以在WebBrowser控件登錄到的站點設置後從WebBrowser控件中檢索必要的cookie,那麼您應該可以在WebRequest/WebClient中使用這些cookie。
This文章概述瞭如何在WebClient上使用cookie;你必須對它進行子類化,但它只是一個需要的覆蓋。
要完成你想要做的事情並不容易。服務器可以使用客戶端(瀏覽器)的兩種身份驗證之一:
1)傳輸身份驗證 2)基於表單的身份驗證。
傳輸驗證:在這種情況下,驗證是使用傳輸連接本身完成的 - 在這裏它將使用自定義HTTP頭與多路握手進行驗證。
基於表單的身份驗證:這是在將憑證輸入表單時完成的傳統身份驗證。
在這兩種情況下,身份驗證可能在您的託管控件實例化時已經發生。正如有人建議你可以竊取該域的瀏覽器cookies,並將其與webclient一起使用,但它可能會或可能不會按照您的預期工作。
如果你想要做的只是下載一些東西,那麼我會看看是否可以使用瀏覽器工具,例如XmlHttpRequest或其他ajax機制來下載你想要的東西作爲所託管頁面的DOM的一部分控制。然後,您可以從您的控件中讀取該內容,或者也可以讓瀏覽器通過調用控件上的方法/屬性的方式將該內容注入到控件中。
[編輯]
找出(使用在Firefox插件螢火蟲)究竟是如何基於窗體身份驗證被在瀏覽器中完成。然後,您可以編寫代碼來完成與瀏覽器完全相同的請求/響應。對於網站來說,客戶端將像任何其他基於瀏覽器的客戶端一樣出現。那麼你應該可以從網站上下載任何你想要的東西。
希望這會有所幫助。
一種可能的方式做到這一點是使用InternetGetCookie函數獲取餅乾,構建相應的cookie
對象,並使用它的CookieContainer
要檢索的HttpOnly餅乾使用InternetGetCookieEx
下面是一些例子:
這不是所有的cookies – ebattulga 2010-08-06 08:19:25
嘗試InternetGetCookieEx與INTERNET_COOKIE_HTTPONLY或INTERNET_COOKIE_THIRD_PARTY – 2010-08-11 17:24:27
INTERNET_COOKIE_HTTPONLY宣佈在哪裏? – 2013-06-08 17:19:10
我實際上在Windows Mobile平臺上經歷了同樣的問題,唯一有效的工作是在發送請求之前擴展WebBrowser控件(使用C++:<)來捕獲POST/GET變量。
這個庫可以幫助你:
http://www.codeproject.com/KB/miscctrl/csEXWB.aspx
「..the庫實現PassthroughAPP包由Igor Tandetnik,使客戶端攔截所有的HTTP和HTTPS請求和響應。」
因此,儘管無法在標準WebBrowser控件上獲得用於基本身份驗證的POST/GET變量,但如果使用擴展控件(例如鏈接的示例),實際上很多「擴展WebBrowser「控件是由於與您非常相似的問題而創建的。不幸的是,據我所知,你需要做到這一點使用非託管代碼/ C++ :(。
你應該能夠.Document.Cookie
然後訪問WebBrowser
控制的cookies在你的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
控制權轉移的cookie來您HTTPWebRequest
類
如果。問題只是「如何將Web瀏覽器身份驗證信息傳輸到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;
}
對於未來參考文獻而言,答案很晚。 WebBrowser
使用UrlMon庫來管理每個進程的會話,因此可以使用UrlMon API(如URLOpenStream或URLDownloadToFile)來下載同一會話中的任何資源(API可以通過P/invoke從C#調用)。類似的問題回答了here。
如果找到了這個解決方案。用下面的信息簡單地創建一個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));
這是我唯一的woking解決方案。解析帶有重定向和SSO的頁面....非常感謝! – 2017-06-25 13:15:54
太棒了!這也是我工作的唯一解決方案。保存了我的一週! – 2017-08-30 14:46:28
我知道這是很老的問題,但沒有答案標記,所以我想分享我準備
我還沒有轉移我的cookies,從網頁瀏覽器的解決方案webrequest,但我用webclient代替網絡請求,爲此,我遵循以下步驟
創建cookie識別的web客戶端從Web瀏覽器控件0解析餅乾 分配解析餅乾餅乾容器 使用的cookie容器 使用的cookie識別Web客戶端對象立即發送您的要求
詳細解釋了這個鏈接http://www.codewithasp.net/2016/06/transferring-cookies-webbrowser-webclient-c-net.html
上創建的cookie識別Web客戶端對象從類的名稱可以假設你問.NET基類庫類? – Oded 2010-08-01 15:13:40
是的。 System.Net.WebRequest – ebattulga 2010-08-01 15:30:35
鏈接需要什麼樣的身份驗證?登錄表單? SSL客戶端證書? Windows身份驗證? – 2010-08-05 06:28:21