Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to transfer authentication from Webbrowser to WebRequest

I'm using webbrowser control to login any site. And then i want to download some sub page html using WebRequest (or WebClient). This links must requires authentication.

How to transfer Webbrowser authentication information to Webrequest or Webclient?

like image 732
ebattulga Avatar asked Aug 01 '10 15:08

ebattulga


7 Answers

If the question is only "How to transfer Webbrowser authentication information to Webrequest or Webclient?" this code is enough:

You can call the GetUriCookieContainer method that returns you a CookieContainer that can be used for subsequent call with WebRequest object.

  [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;
}
like image 71
Alkampfer Avatar answered Oct 03 '22 13:10

Alkampfer


If found this solution. Simple create a Class.cs file with the information below and call the static GetCookieInternal function.

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();
    }
}   

Sample:

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));
like image 31
Roger Barreto Avatar answered Oct 03 '22 14:10

Roger Barreto


You should be able to access the cookies of the WebBrowser control with .Document.Cookie then in your HTTPWebRequest you can add that cookie to its cookie container.
Here is an example (VB.NET because I'm most familiar there):

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)

And that should transfer the cookie from your WebBrowser control over to your HTTPWebRequest class.

like image 39
Justin Avatar answered Oct 03 '22 15:10

Justin


One possible way to do this is to get the cookie by using InternetGetCookie function, construct corresponding cookie object and use it for the CookieContainer

To retrieve HttpOnly cookies use InternetGetCookieEx

Here are some examples:

InternetGetCookie() in .NET

Download using Internet Explorer Cookies

like image 24
Giorgi Avatar answered Oct 03 '22 15:10

Giorgi


If you can retrieve the necessary cookies from the WebBrowser control after they are set by the site you are logging into, you should be able to use those same cookies with WebRequest/WebClient.

This article outlines how to use cookies with a WebClient; you have to subclass it, but it's only a single override that's needed.

like image 40
Bojan Rajkovic Avatar answered Oct 03 '22 14:10

Bojan Rajkovic


A late answer for future references. WebBrowser uses UrlMon library which manages the session per-process, so UrlMon APIs like URLOpenStream or URLDownloadToFile can be used to download any resource on the same session (the APIs can be called from C# via P/invoke). A similar question answered here.

like image 30
noseratio Avatar answered Oct 03 '22 13:10

noseratio


I know this is very old question but there is answer marked so I want to share the solution I prepared

I have not transferred my cookies from webbrowser to webrequest but I used webclient in place of webrequest and for this there are below steps I followed

Create cookie aware web client Parse cookies from web browser control Assign parsed cookies to cookie container Create cookie aware web client object using cookie container Use cookie aware web client object to send your requests now

Explained in details on this link http://www.codewithasp.net/2016/06/transferring-cookies-webbrowser-webclient-c-net.html

like image 32
Nikhil Gaur Avatar answered Oct 03 '22 13:10

Nikhil Gaur