Можно ли передать аутентификацию из Webbrowser в WebRequest? - PullRequest
36 голосов
/ 01 августа 2010

Я использую контроль веб-браузера для входа на любой сайт. И тогда я хочу скачать некоторые html-страницы с помощью WebRequest (или WebClient). Эта ссылка должна требовать аутентификации.

Как передать информацию аутентификации Webbrowser в Webrequest или Webclient?

Ответы [ 9 ]

40 голосов
/ 12 апреля 2011

Если вопрос только "Как перенести информацию аутентификации 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;
}
7 голосов
/ 16 декабря 2014

Если найдено это решение. Просто создайте файл 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));
3 голосов
/ 11 августа 2010

Вы должны иметь доступ к файлам cookie элемента управления WebBrowser с помощью .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)

И это должно передать куки из вашего WebBrowser элемента управления в ваш HTTPWebRequest класс.

2 голосов
/ 05 августа 2010

Один из возможных способов сделать это - получить файл cookie с помощью функции InternetGetCookie , создать соответствующий объект cookie и использовать его для CookieContainer

. Для получения файлов cookie HttpOnly используйте InternetGetCookieEx

Вот несколько примеров:

InternetGetCookie () в .NET

Загрузка с использованием файлов cookie Internet Explorer

1 голос
/ 11 июня 2016

Я знаю, что это очень старый вопрос, но есть помеченный ответ, поэтому я хочу поделиться подготовленным мною решением.

Я не перенес свои куки из веб-браузера в веб-запрос, но вместо веб-запроса я использовал веб-клиент и для негониже приведены шаги, которые я выполнил

Создание веб-клиента с поддержкой файлов cookie Разбор файлов cookie с помощью элемента управления веб-браузера Назначение проанализированных файлов cookie для контейнера cookie Создание объекта веб-клиента с поддержкой файлов cookie с использованием контейнера cookie Используйте объект веб-клиента с поддержкой файлов cookie для отправки ваших запросов сейчас

Подробно объяснено по этой ссылке http://www.codewithasp.net/2016/06/transferring-cookies-webbrowser-webclient-c-net.html

1 голос
/ 27 сентября 2013

Поздний ответ для будущих ссылок. WebBrowser использует библиотеку UrlMon , которая управляет сеансом для каждого процесса, поэтому такие API-интерфейсы UrlMon, как URLOpenStream или URLDownloadToFile , можно использовать для загрузки любого ресурса в том же сеансе (API можно вызывать из C # через P / invoke). На аналогичный вопрос ответил здесь .

1 голос
/ 01 августа 2010

Если вы можете получить необходимые файлы cookie из элемента управления WebBrowser после того, как они установлены сайтом, на котором вы входите, вы сможете использовать эти же файлы cookie с WebRequest / WebClient.

В этой статье рассказывается, как использовать куки с WebClient; Вы должны создать его подкласс, но требуется только одно переопределение.

0 голосов
/ 09 августа 2010

На самом деле я столкнулся с этой же проблемой на платформе Windows Mobile, и единственное, что сработало, - это расширение элемента управления WebBrowser (с помощью C ++: <) для захвата переменных POST / GET перед отправкой запроса. </p>

Эта библиотека может вам помочь:

http://www.codeproject.com/KB/miscctrl/csEXWB.aspx

".. библиотека реализует пакет PassthroughAPP от Игоря Тандетника, который позволяет клиенту перехватывать все HTTP и HTTPSзапрос и ответы. "

Таким образом, хотя невозможно получить переменные POST / GET, используемые для вашей базовой аутентификации на стандартном элементе управления WebBrowser, это было бы возможно, если бы вы использовали расширенный элемент управления, такой как пример Iсвязанный - фактически многие элементы управления «Extended WebBrowser» созданы из-за проблем, очень похожих на ваши.К сожалению, насколько я знаю, вам нужно сделать это с помощью неуправляемого кода / c ++: (.

0 голосов
/ 03 августа 2010

Нелегко выполнить то, что вы пытаетесь сделать. Сервер может использовать один из двух типов аутентификации с клиентом (браузером)

1) Транспортная аутентификация 2) Форма на основе аутентификации.

Транспортная аутентификация: в этом случае аутентификация выполняется с использованием самого транспортного соединения - здесь для аутентификации будут использоваться настраиваемые заголовки HTTP с многоканальным рукопожатием.

Проверка подлинности на основе форм: это традиционная проверка подлинности, которая выполняется при вводе учетных данных в форму.

В любом случае аутентификация может уже произойти к моменту создания вашего управляемого элемента управления. Как кто-то предложил, вы можете украсть куки браузера для этого домена и использовать его с веб-клиентом, но тогда он может работать, а может и не работать так, как вы ожидаете.

Если все, что вы хотите сделать, это загрузить что-то, то я бы посмотрел, смогу ли я использовать возможности браузеров, например, XmlHttpRequest или какой-либо другой механизм ajax, чтобы загрузить то, что вы хотите, как часть DOM страницы, на которой размещается контроль. Затем вы можете прочитать этот контент из своего элемента управления или сделать так, чтобы браузер вводил этот контент в ваш элемент управления с помощью Javascript, вызывающего метод / свойство вашего элемента управления.

[EDIT]

Узнайте (используя плагин Firebug в Firefox), как именно выполняется аутентификация на основе форм в браузере. Затем вы можете написать код, который будет выполнять тот же запрос / ответ, что и браузер. На веб-сайте клиент будет выглядеть как любой другой клиент на основе браузера. Тогда вы сможете скачивать с сайта все, что захотите.

Надеюсь, это поможет.

...