2010-08-01 17 views
35

Estoy utilizando el control webbrowser para iniciar sesión en cualquier sitio. Y luego quiero descargar un html de sub página utilizando WebRequest (o WebClient). Este enlace debe requerir autenticación.¿Es posible transferir la autenticación de Webbrowser a WebRequest

Cómo transferir la información de autenticación de Webbrowser a Webrequest o Webclient?

+0

¿De los nombres de las clases se puede suponer que estás preguntando sobre las clases de biblioteca de la clase base de .NET? – Oded

+0

sí. System.Net.WebRequest – ebattulga

+0

¿Qué tipo de autenticación requieren los enlaces? ¿Un formulario de inicio de sesión? Certificado de cliente SSL? Autenticación de Windows? –

Respuesta

1

Si puede recuperar las cookies necesarias del control WebBrowser después de que las haya configurado el sitio en el que está iniciando sesión, debería poder utilizar esas mismas cookies con WebRequest/WebClient.

This El artículo describe cómo usar cookies con un WebClient; tienes que crear una subclase, pero solo se necesita una sola anulación.

+0

Estoy tratando de conseguir galletas. Pero webbrowser.document.cookie es nulo – ebattulga

+0

@ebattulga - si la cookie es 'HttpOnly', no se puede recuperar desde javascript. http://msdn.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx – Giorgi

0

No es fácil lograr lo que estás tratando de hacer. El servidor podría estar utilizando uno de los dos tipos de autenticación con el cliente (navegador)

1) Autenticación de transporte 2) Autorización basada en formularios.

Autor de transporte: en este caso, la autenticación se realiza utilizando la conexión de transporte en sí misma; aquí usará encabezados HTTP personalizados con un handshake de múltiples vías para realizar la autenticación.

Autorización basada en formularios: esta es la autenticación tradicional que se realiza al ingresar sus credenciales en un formulario.

En cualquier caso, la autenticación podría haber ocurrido antes de la instancia de su control administrado. Como alguien sugirió que puede robar las cookies de los navegadores para ese dominio y usarlo con webclient, pero puede que funcione o no de la manera esperada.

Si todo lo que quieres hacer es descargar algo, entonces vería si pudiera usar las herramientas de los navegadores para, por ejemplo, XmlHttpRequest u otro mecanismo de Ajax para descargar lo que quieras como parte del DOM de la página que aloja el control. Entonces podría leer ese contenido desde su control, o también podría hacer que el navegador inserte ese contenido en su control mediante un método que llama a un método/propiedad en su control.

[EDIT]

Averigüe (usando el plugin Firebug en Firefox) exactamente cómo las formas de autenticación basada en que se está haciendo en el navegador. Luego puede escribir código para hacer exactamente la misma solicitud/respuesta que está haciendo el navegador. Para el sitio web, el cliente aparecerá como cualquier otro cliente basado en navegador. Entonces deberías poder descargar todo lo que quieras del sitio web.

Espero que esto ayude.

2

Una posible manera de hacer esto es conseguir la cookie utilizando InternetGetCookie función, construcción correspondiente cookie objeto y lo utilizan para la CookieContainer

Para recuperar HttpOnly uso de cookies InternetGetCookieEx

Éstos son algunos ejemplos:

InternetGetCookie() in .NET

Download using Internet Explorer Cookies

+0

Eso no es obtener todas las cookies – ebattulga

+0

Pruebe InternetGetCookieEx con INTERNET_COOKIE_HTTPONLY o INTERNET_COOKIE_THIRD_PARTY –

+1

donde se declara INTERNET_COOKIE_HTTPONLY? –

0

En realidad, he pasado por el mismo problema en la plataforma Windows Mobile y lo único que funcionó fue extender el control WebBrowser (utilizando C++: <) para capturar los valores POST/GET antes de enviar la solicitud.

Esta biblioteca puede ayudarle a cabo:

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

"..la biblioteca implementa el paquete PassthroughAPP por Igor Tandetnik, que permite al cliente para interceptar todas las solicitudes y respuestas HTTP y HTTPS."

Así que aunque no es posible obtener los vars POST/GET utilizados para su autenticación básica en un control WebBrowser estándar, sería posible si utiliza un control extendido como la muestra que vinculaba, de hecho muchos "Extended Los controles de WebBrowser "se crean debido a problemas muy similares a los tuyos. Por desgracia, por lo que yo sé lo que necesita hacer esto utilizando el código no administrado/C++ :(.

3

Usted debe ser capaz de acceder a las cookies del control WebBrowser con .Document.Cookie entonces en su HTTPWebRequest puede agregar esa cookie a su galletas . contenedor
Aquí es un ejemplo (VB.NET, ya que estoy más familiarizado allí):

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) 

Y eso debería transferir la cookie de su mando a WebBrowser encima a su clase HTTPWebRequest

+0

browser.Document.Cookie is null – ebattulga

+0

¿Se ha conectado y autenticado con el control de su navegador web antes de leer el valor .Document.Cookie? – Justin

+0

WebBrowser.Document.Cookie no contiene cookies HttpOnly. –

40

Si. la pregunta es solo "¿Cómo transferir la información de autenticación de Webbrowser a Webrequest o Webclient?" este código es suficiente:

Puede llamar al método GetUriCookieContainer que le devuelve un CookieContainer que se puede usar para una llamada posterior con el objeto 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; 
} 
+0

Tenga en cuenta que esto no incluirá cookies "seguras" de manera predeterminada. Para obtenerlos solo tendrías que pasar un URI que comienza con https en lugar de http. – AaronLS

+2

+1 para bandera HttpOnly. – Jaanus

+0

En realidad, no tengo idea de dónde poner o usar este código, ¿podría ayudarme con eso? –

1

Una respuesta tardía para futuras referencias. WebBrowser utiliza la biblioteca UrlMon que gestiona la sesión por proceso, por lo que las API de UrlMon como URLOpenStream o URLDownloadToFile se pueden usar para descargar cualquier recurso en la misma sesión (las API pueden llamarse desde C# a través de P/invocar). Una pregunta similar respondió here.

7

Si encontró esta solución. Simple crea un archivo Class.cs con la información siguiente y llama a la función estática 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(); 
    } 
} 

muestra:

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)); 
+1

Esta es la única solución de trabajo para mí. Página de análisis con redirecciones y SSO ... ¡Muchas gracias! –

+0

¡Genial! Esa es también la única solución que funcionó para mí también. Guardado mi semana! –

1

Sé que esto es muy vieja pregunta, pero no hay respuesta marcada, así que quiero compartir la solución preparé

no he transferido mis cookies de navegador web a la webrequest pero utilicé webclient en lugar de webrequest y para esto hay los siguientes pasos seguí

Create cookie aware web client Galletas Parse de control de explorador Web Asignar analizan cookies para contenedores de galletas Crear galletas conscientes de objetos de cliente web utilizando contenedores de galletas uso de cookies de objetos de cliente conscientes web para enviar sus peticiones ahora

Se explica en detalles en este enlace http://www.codewithasp.net/2016/06/transferring-cookies-webbrowser-webclient-c-net.html

Cuestiones relacionadas