C# Web 浏览器控件下载(无提示 + 证书 SSL + WebForms)

本文关键字:证书 SSL WebForms 提示 浏览器 Web 控件 下载 | 更新日期: 2023-09-27 18:34:27

问题:

  1. 捕获所有 ASP.NET 视图状态回发数据
  2. 在SSLEnabled-WebClient中模拟Web浏览器的会话/Cookie状态
  3. 通过SSLEnabled-WebClient发送WebForm POSTDATA以自动下载文件
  4. 管理文件

挖掘我复杂问题的任何解决方案,终于我找到了解决方案。

C# Web 浏览器控件下载(无提示 + 证书 SSL + WebForms)

  1. 将 MSHTML 引用添加到项目中 c:'windows'system32 or WOW64'mshtml.dll

  2. 使用JQuery.serialize()我可以设法从Top ASP.NET Form中获取FormData。

    2.1 将 Jquery 库附加到您的 Web 浏览器当前页面

    HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
    HtmlElement scriptEl1 = webBrowser1.Document.CreateElement("script");
    scriptEl1.SetAttribute("src", "https://code.jquery.com/jquery-1.11.1.min.js");
    head.AppendChild(scriptEl1);
    

    2.2 创建一个新的div HTML 元素,通过脚本接收 postData

    HtmlElement scriptEl2 = webBrowser1.Document.CreateElement("script");
    mshtml.IHTMLScriptElement element = (mshtml.IHTMLScriptElement)scriptEl2.DomElement;
    element.text = @"
    function CreatePostData() { 
         //alert('Jquery online');
         var postData = jQuery(document.forms[0]).serialize();
         var divPost = document.createElement(""DIV"");
         divPost.innerText = postData;
         divPost.id = ""divPost"";
         document.body.appendChild(divPost);
         //alert(divPost.innerText);
    }";
    head.AppendChild(scriptEl2);
    webBrowser1.Document.InvokeScript("CreatePostData");
    string postData = webBrowser1.Document.GetElementById("divPost").InnerText;
    
  3. 拥有PostData后,您现在需要启用WebClient SSLSecure。

    class SecureWebClient : WebClient
    {
        protected override WebRequest GetWebRequest(Uri address)
        {
            HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
            string certPath = @"C:'TEMP'ClientCertificateFile.cer";
            X509Certificate myCert = X509Certificate.CreateFromCertFile(certPath);
            request.ClientCertificates.Add(myCert);
            return request;
        }
    }
    
  4. 现在您必须将相同的WebBrowser状态与WebClient的状态同步,某些网站/系统为此使用HTTPOnly cookie,这就是我的情况。这些 cookie 默认情况下不会在 WebBrowser Document.Cookie 属性中出现,以克服对

     var cookies = FullWebBrowserCookie.GetCookieInternal(webBrowser1.Url, false);` 
    

    如果您需要如上所述使用 HTTPOnly cookie,请在项目中添加另一个类:

    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();
    }   }
    
  5. 将 WebControl 状态与 WebClient 同步,发出 PostData 并捕获返回的 byteArray:

    SecureWebClient wc = new SecureWebClient();
    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));
    File.WriteAllBytes(@"C:'Temp'<FileName>", result);
    wc.Dispose();