【问题标题】:c# proxy authentication using wininetc# 使用wininet进行代理认证
【发布时间】:2017-05-06 06:11:33
【问题描述】:

使用wininet的c#代理认证; 我应该确保代理只在 winforms 应用程序(webbrowser 控件)内工作,而不是系统范围内。

这是我使用的代理类;

public static class WinInetInterop
    {
        public static string applicationName;

        [DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr InternetOpen(
            string lpszAgent, int dwAccessType, string lpszProxyName,
            string lpszProxyBypass, int dwFlags);

        [DllImport("wininet.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool InternetCloseHandle(IntPtr hInternet);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        private struct INTERNET_PER_CONN_OPTION_LIST
        {
            public int Size;

            // The connection to be set. NULL means LAN.
            public System.IntPtr Connection;

            public int OptionCount;
            public int OptionError;

            // List of INTERNET_PER_CONN_OPTIONs.
            public System.IntPtr pOptions;
        }
        private enum INTERNET_OPTION
        {
            // Sets or retrieves an INTERNET_PER_CONN_OPTION_LIST structure that specifies
            // a list of options for a particular connection.
            INTERNET_OPTION_PER_CONNECTION_OPTION = 75,

            // Notify the system that the registry settings have been changed so that
            // it verifies the settings on the next call to InternetConnect.
            INTERNET_OPTION_SETTINGS_CHANGED = 39,

            // Causes the proxy data to be reread from the registry for a handle.
            INTERNET_OPTION_REFRESH = 37

        }

        private enum INTERNET_PER_CONN_OptionEnum
        {
            INTERNET_PER_CONN_FLAGS = 1,
            INTERNET_PER_CONN_PROXY_SERVER = 2,
            INTERNET_PER_CONN_PROXY_BYPASS = 3,
            INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
            INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5,
            INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6,
            INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7,
            INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8,
            INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9,
            INTERNET_PER_CONN_FLAGS_UI = 10
        }
        private const int INTERNET_OPEN_TYPE_DIRECT = 1;  // direct to net
        private const int INTERNET_OPEN_TYPE_PRECONFIG = 0; // read registry
                                                            /// <summary>
                                                            /// Constants used in INTERNET_PER_CONN_OPTON struct.
                                                            /// </summary>
        private enum INTERNET_OPTION_PER_CONN_FLAGS
        {
            PROXY_TYPE_DIRECT = 0x00000001,   // direct to net
            PROXY_TYPE_PROXY = 0x00000002,   // via named proxy
            PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,   // autoproxy URL
            PROXY_TYPE_AUTO_DETECT = 0x00000008   // use autoproxy detection
        }

        /// <summary>
        /// Used in INTERNET_PER_CONN_OPTION.
        /// When create a instance of OptionUnion, only one filed will be used.
        /// The StructLayout and FieldOffset attributes could help to decrease the struct size.
        /// </summary>
        [StructLayout(LayoutKind.Explicit)]
        private struct INTERNET_PER_CONN_OPTION_OptionUnion
        {
            // A value in INTERNET_OPTION_PER_CONN_FLAGS.
            [FieldOffset(0)]
            public int dwValue;
            [FieldOffset(0)]
            public System.IntPtr pszValue;
            [FieldOffset(0)]
            public System.Runtime.InteropServices.ComTypes.FILETIME ftValue;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct INTERNET_PER_CONN_OPTION
        {
            // A value in INTERNET_PER_CONN_OptionEnum.
            public int dwOption;
            public INTERNET_PER_CONN_OPTION_OptionUnion Value;
        }
        /// <summary>
        /// Sets an Internet option.
        /// </summary>
        [DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern bool InternetSetOption(
            IntPtr hInternet,
            INTERNET_OPTION dwOption,
            IntPtr lpBuffer,
            int lpdwBufferLength);

        /// <summary>
        /// Queries an Internet option on the specified handle. The Handle will be always 0.
        /// </summary>
        [DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true,
            EntryPoint = "InternetQueryOption")]
        private extern static bool InternetQueryOptionList(
            IntPtr Handle,
            INTERNET_OPTION OptionFlag,
            ref INTERNET_PER_CONN_OPTION_LIST OptionList,
            ref int size);

        /// <summary>
        /// Set the proxy server for LAN connection.
        /// </summary>
        public static bool SetConnectionProxy(string proxyServer)
        {

            IntPtr hInternet = InternetOpen(applicationName, INTERNET_OPEN_TYPE_DIRECT, null, null, 0);

            //// Create 3 options.
            //INTERNET_PER_CONN_OPTION[] Options = new INTERNET_PER_CONN_OPTION[3];

            // Create 2 options.
            INTERNET_PER_CONN_OPTION[] Options = new INTERNET_PER_CONN_OPTION[2];

            // Set PROXY flags.
            Options[0] = new INTERNET_PER_CONN_OPTION();
            Options[0].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS;
            Options[0].Value.dwValue = (int)INTERNET_OPTION_PER_CONN_FLAGS.PROXY_TYPE_PROXY;

            // Set proxy name.
            Options[1] = new INTERNET_PER_CONN_OPTION();
            Options[1].dwOption =
                (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER;
            Options[1].Value.pszValue = Marshal.StringToHGlobalAnsi(proxyServer);

            //// Set proxy bypass.
            //Options[2] = new INTERNET_PER_CONN_OPTION();
            //Options[2].dwOption =
            //    (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_BYPASS;
            //Options[2].Value.pszValue = Marshal.StringToHGlobalAnsi(“local”);

            //// Allocate a block of memory of the options.
            //System.IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(Options[0])
            //    + Marshal.SizeOf(Options[1]) + Marshal.SizeOf(Options[2]));

            // Allocate a block of memory of the options.
            System.IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(Options[0])
                + Marshal.SizeOf(Options[1]));

            System.IntPtr current = buffer;

            // Marshal data from a managed object to an unmanaged block of memory.
            for (int i = 0; i < Options.Length; i++)
            {
                Marshal.StructureToPtr(Options[i], current, false);
                // current = (System.IntPtr)((int)current + Marshal.SizeOf(Options[i])); 
                current = (System.IntPtr)((Environment.Is64BitProcess ? current.ToInt64() : current.ToInt32()) + Marshal.SizeOf(Options[i]));
            }

            // Initialize a INTERNET_PER_CONN_OPTION_LIST instance.
            INTERNET_PER_CONN_OPTION_LIST option_list = new INTERNET_PER_CONN_OPTION_LIST();

            // Point to the allocated memory.
            option_list.pOptions = buffer;

            // Return the unmanaged size of an object in bytes.
            option_list.Size = Marshal.SizeOf(option_list);

            // IntPtr.Zero means LAN connection.
            option_list.Connection = IntPtr.Zero;

            option_list.OptionCount = Options.Length;
            option_list.OptionError = 0;
            int size = Marshal.SizeOf(option_list);

            // Allocate memory for the INTERNET_PER_CONN_OPTION_LIST instance.
            IntPtr intptrStruct = Marshal.AllocCoTaskMem(size);

            // Marshal data from a managed object to an unmanaged block of memory.
            Marshal.StructureToPtr(option_list, intptrStruct, true);

            // Set internet settings.
            bool bReturn = InternetSetOption(hInternet,
                INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION, intptrStruct, size);

            // Free the allocated memory.
            Marshal.FreeCoTaskMem(buffer);
            Marshal.FreeCoTaskMem(intptrStruct);
            InternetCloseHandle(hInternet);

            // Throw an exception if this operation failed.
            if (!bReturn)
            {
                throw new ApplicationException("Set Internet Option Failed!");
            }

            return bReturn;
        }



        /// <summary>
        /// Backup the current options for LAN connection.
        /// Make sure free the memory after restoration. 
        /// </summary>
        private static INTERNET_PER_CONN_OPTION_LIST GetSystemProxy()
        {

            // Query following options. 
            INTERNET_PER_CONN_OPTION[] Options = new INTERNET_PER_CONN_OPTION[3];

            Options[0] = new INTERNET_PER_CONN_OPTION();
            Options[0].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS;
            Options[1] = new INTERNET_PER_CONN_OPTION();
            Options[1].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER;
            Options[2] = new INTERNET_PER_CONN_OPTION();
            Options[2].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_BYPASS;

            // Allocate a block of memory of the options.
            System.IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(Options[0])
                + Marshal.SizeOf(Options[1]) + Marshal.SizeOf(Options[2]));

            System.IntPtr current = (System.IntPtr)buffer;

            // Marshal data from a managed object to an unmanaged block of memory.
            for (int i = 0; i < Options.Length; i++)
            {
                Marshal.StructureToPtr(Options[i], current, false);
                current = (System.IntPtr)((int)current + Marshal.SizeOf(Options[i]));
            }

            // Initialize a INTERNET_PER_CONN_OPTION_LIST instance.
            INTERNET_PER_CONN_OPTION_LIST Request = new INTERNET_PER_CONN_OPTION_LIST();

            // Point to the allocated memory.
            Request.pOptions = buffer;

            Request.Size = Marshal.SizeOf(Request);

            // IntPtr.Zero means LAN connection.
            Request.Connection = IntPtr.Zero;

            Request.OptionCount = Options.Length;
            Request.OptionError = 0;
            int size = Marshal.SizeOf(Request);

            // Query internet options. 
            bool result = InternetQueryOptionList(IntPtr.Zero,
                INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION,
                ref Request, ref size);
            if (!result)
            {
                throw new ApplicationException("Set Internet Option Failed!");
            }

            return Request;
        }

        /// <summary>
        /// Restore the options for LAN connection.
        /// </summary>
        /// <param name=”request”></param>
        /// <returns></returns>
        public static bool RestoreSystemProxy()
        {

            IntPtr hInternet = InternetOpen(applicationName, INTERNET_OPEN_TYPE_DIRECT, null, null, 0);

            INTERNET_PER_CONN_OPTION_LIST request = GetSystemProxy();
            int size = Marshal.SizeOf(request);

            // Allocate memory. 
            IntPtr intptrStruct = Marshal.AllocCoTaskMem(size);

            // Convert structure to IntPtr 
            Marshal.StructureToPtr(request, intptrStruct, true);

            // Set internet options.
            bool bReturn = InternetSetOption(hInternet,
                INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION,
                intptrStruct, size);

            // Free the allocated memory.
            Marshal.FreeCoTaskMem(request.pOptions);
            Marshal.FreeCoTaskMem(intptrStruct);

            if (!bReturn)
            {
                throw new ApplicationException("Set Internet Option Failed!");
            }

            // Notify the system that the registry settings have been changed and cause
            // the proxy data to be reread from the registry for a handle.
            InternetSetOption(hInternet, INTERNET_OPTION.INTERNET_OPTION_SETTINGS_CHANGED,
                IntPtr.Zero, 0);
            InternetSetOption(hInternet, INTERNET_OPTION.INTERNET_OPTION_REFRESH,
                IntPtr.Zero, 0);

            InternetCloseHandle(hInternet);

            return bReturn;
        }

    }

我以这种方式使用该类,它工作正常;

WinInetInterop.RestoreSystemProxy(); WinInetInterop.SetConnectionProxy(123.456.789.99:80);

由于好的代理服务总是需要认证,我不得不像这样使用代理认证; 123.456.789.99:80:用户名:密码 和 WinInetInterop.SetConnectionProxy(123.456.789.99:80:username:password) 不起作用。

我用谷歌搜索了网页,但找不到除此之外的解决方案;

“一旦您从代理获得 407 响应,您总是可以直接使用 WinINet 函数进行代理身份验证。这是一篇关于此的文章(不,我没有 .NET 示例,但您可以编写一个我确定) :http://msdn.microsoft.com/en-us/library/windows/desktop/aa384220(v=vs.85).aspx"

由于我是新手,因此无法为此编写代码。 我尝试了几天,但无法解决。请帮帮我。

【问题讨论】:

    标签: c# authentication proxy credentials wininet


    【解决方案1】:

    对于代理身份验证,WebBroser ActiveX 控件调用主机 ole 客户端站点的 IServiceProvider.QueryService 方法来查找其 SID_IAuthenticate 服务。

    对于 WinForms,客户端站点是 WebBrowser.WebBrowserSite 类。您可以从中派生以添加您自己的 IServiceProvider 和 IAuthenticate 实现,然后覆盖 WebBrowser.CreateWebBrowserSiteBase 方法以使用您的扩展 ole 客户端站点而不是默认站点。

    【讨论】:

    • 哇哇哇哇哇哇哇?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 2015-12-07
    • 2019-09-30
    相关资源
    最近更新 更多