是否可以将身份验证从Webbrowser转移到WebRequest

eba*_*lga 36 c# webclient httpwebrequest webbrowser-control

我正在使用webbrowser控件登录任何网站.然后我想使用WebRequest(或WebClient)下载一些子页面html.此链接必须要求身份验证.

如何将Webbrowser身份验证信息传输到Webrequest或Webclient?

Alk*_*fer 40

如果问题只是"如何将Webbrowser身份验证信息传输到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;
}
Run Code Online (Sandbox Code Playgroud)


Rog*_*eto 8

如果找到这个解决方案 使用下面的信息简单地创建一个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();
    }
}   
Run Code Online (Sandbox Code Playgroud)

样品:

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));
Run Code Online (Sandbox Code Playgroud)


Jus*_*tin 5

您应该能够访问WebBrowser控件的 cookie,.Document.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)
Run Code Online (Sandbox Code Playgroud)

这应该将 cookie 从您的WebBrowser控制转移到您的HTTPWebRequest班级。


Boj*_*vic 1

如果您可以在您登录的站点设置必要的 cookie 后从 WebBrowser 控件中检索这些 cookie,那么您应该能够在 WebRequest/WebClient 中使用这些相同的 cookie。

本文概述了如何在 WebClient 中使用 cookie;您必须对其进行子类化,但这只需要一次覆盖。