Is it possible to transfer authentication from Webbrowser to WebRequest

后端 未结 9 2062
无人共我
无人共我 2020-11-27 14:10

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.

相关标签:
9条回答
  • 2020-11-27 14:20

    I've actually been through this same problem on the Windows Mobile platform, and the only thing that worked was to extend the WebBrowser control (using C++ :<) to capture the POST/GET vars before the request is sent.

    This library may help you out:

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

    "..the library implements the PassthroughAPP package by Igor Tandetnik, which enables the client to intercept all HTTP and HTTPS request and responses."

    So although it is not possible to get the POST/GET vars used for your basic auth on a standard WebBrowser control, it would be possible if you use an extended control such as the sample I linked - in fact many "Extended WebBrowser" controls are created because of problems very similar to yours. Unfortunately, as far as I know you need to do this using unmanaged code/c++ :(.

    0 讨论(0)
  • It is not easy to accomplish what you are trying to do. The server could be using one of two types of authentication with the client (browser)

    1) Transport authentication 2) Forms based auth.

    Transport auth: In this case, the authentication is done using the transport connection itself - here it will use custom HTTP headers with a multiway handshake to do the auth.

    Forms based auth:This is the traditional auth that is done when you enter your credentials into a form.

    In either case, the authentication might have already happened by the time your managed control is instantiated. As someone suggested you can steal the browsers cookies for that domain and use it with webclient but then it may or may not work the way you expect.

    If all you want to do is download something, then I would see if I could use the browsers facilities for eg, XmlHttpRequest or some other ajax mechanism to download what you want as part of the DOM of the page that is hosting the control. Then you could read that content from your control, or you could also have the browser inject that content into your control by way of Javascript calling a method/property on your control.

    [EDIT]

    Find out (using Firebug plugin in firefox) exactly how the forms based auth is being done in the browser. Then you can write code to do exactly the same request/response that the browser is doing. To the website, the client will appear like any other browser based client. Then you should be able to download anything you want from the website.

    Hope this helps.

    0 讨论(0)
  • 2020-11-27 14:29

    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

    0 讨论(0)
  • 2020-11-27 14:32

    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));
    
    0 讨论(0)
  • 2020-11-27 14:34

    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

    0 讨论(0)
  • 2020-11-27 14:37

    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.

    0 讨论(0)
提交回复
热议问题