2017-05-06 15 views
0

wininet을 사용하는 프록시 인증. 프록시가 시스템 전체가 아닌 winforms appplication (webbrowser 컨트롤) 내에서만 작동하는지 확인해야합니다.C# wininet을 사용하는 프록시 인증

이것은 내가 사용하는 프록시 클래스입니다.

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:username:password 및 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 "

나는 초보자이므로이 코드를 작성할 수 없습니다. 며칠 동안 노력했지만 해결할 수 없었습니다. 도와주세요.

답변

0

프록시 인증의 경우 WebBroser ActiveX 컨트롤은 호스트 OLE 클라이언트 사이트의 IServiceProvider.QueryService 메서드를 호출하여 해당 SID_IAuthenticate 서비스를 찾습니다.

WinForms의 경우 클라이언트 사이트는 WebBrowser.WebBrowserSite 클래스입니다. 자체 IServiceProvider 및 IAuthenticate 구현을 추가하고 WebBrowser.CreateWebBrowserSiteBase 메서드를 재정 의하여 기본 OLY 클라이언트 사이트 대신 확장 된 OL 클라이언트 사이트를 사용할 수 있습니다.