2017-09-08 3 views
0

Je dois obtenir les informations d'identification par défaut de l'utilisateur actuellement connecté et les transmettre à mon service Windows pour vérifier la connectivité Internet et télécharger des fichiers vers Dropbox. Je ne veux pas que l'utilisateur confirme ses identifiants à chaque fois. Alors, comment est-il possible d'obtenir les paramètres de proxy de l'utilisateur actuellement actif + nom d'utilisateur + mot de passe?Comment passer des informations Webcredentials d'un utilisateur actif au service Windows?

Ceci est mon code pour récupérer l'utilisateur actuel

private static string UserName() 
    { 
     string userName = null; 
     ManagementScope ms = new ManagementScope(); 
     ObjectQuery qry = new ObjectQuery("Select * from Win32_ComputerSystem"); 
     ManagementObjectSearcher search = new ManagementObjectSearcher(ms, qry); 
     ManagementObjectCollection result = search.Get(); 
     foreach (ManagementObject rec in result) 
      userName = rec["UserName"] as string; 
     string[] buffer = userName.Split('\\'); 
     return buffer[1]; 
    } 

et ce code est utilisé pour obtenir la WindowsIdentity:

private static WindowsIdentity GetWindowsIdentity() 
    { 
     string userName = UserName(); 
     PrincipalContext ctx = new PrincipalContext(ContextType.Domain); 
     using (UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, userName) ?? 
      UserPrincipal.FindByIdentity(UserPrincipal.Current.Context, IdentityType.UserPrincipalName, userName)) 
     { 
      return user == null 
       ? null 
       : new WindowsIdentity(user.UserPrincipalName); 
     } 
    } 

Voici ce que je veux faire via le service:

System.Diagnostics.Debugger.Launch(); //launch debugger when service runs 

      WindowsImpersonationContext impersonationContext; 
      impersonationContext = GetWindowsIdentity().Impersonate(); 
//try to use the currently logged in user's credentials 
      WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials; 
      try 
      { 
       WebClient wClient = new WebClient(); 
       string xx = wClient.DownloadString(@"https://dropbox.com"); 
       if (xx == "") //just download the sourcecode to chek if this page is available 
        return false; 
      } 
      catch (Exception ex) 
      { 
       using (StreamWriter sw = new StreamWriter(@"C:\Users\Testuser\Desktop\DownloadError.txt", true)) 
       { 
        sw.WriteLine(ex.ToString()); 
       } 
       return false; 
      } 
      impersonationContext.Undo(); 

Le fichier errorLog indique toujours que le service n'a pas pu se connecter. Quand je l'exécute à partir d'une console ou d'applications WinForms, cela fonctionne sans aucun problème.

Errorlog:

System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 172.217.17.238:80 
    at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) 
    at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception) 
    --- End of inner exception stack trace --- 
    at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request) 
    at System.Net.WebClient.DownloadString(Uri address) 
    at System.Net.WebClient.DownloadString(String address) 
    at BeeShotService.Sender.TrySend(String s) in C:\Users\Testuser\Documents\Visual Studio 2017\Projects\Project_BackupUploder\UploaderService\Sender.cs:Zeile 70. 

Répondre

0

J'ai réussi à résoudre le problème pour webRequests simples avec une classe supplémentaire:

class GetProxySettings 
{ 
    private const int INTERNET_OPTION_PROXY = 38; 

    [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern bool InternetQueryOption(IntPtr hInternet, uint dwOption, IntPtr lpBuffer, ref int lpdwBufferLength); 

    /// <summary> 
    /// Access types supported by InternetOpen function. 
    /// </summary>   
    private enum InternetOpenType 
    { 
     INTERNET_OPEN_TYPE_PRECONFIG = 0, 
     INTERNET_OPEN_TYPE_DIRECT = 1, 
     INTERNET_OPEN_TYPE_PROXY = 3, 
    } 

    /// <summary> 
    /// Contains information that is supplied with the INTERNET_OPTION_PROXY value 
    /// to get or set proxy information on a handle obtained from a call to 
    /// the InternetOpen function. 
    /// </summary> 
    private struct INTERNET_PROXY_INFO 
    { 
     public InternetOpenType DwAccessType 
     { 
      get; set; 
     } 
     public string LpszProxy 
     { 
      get; set; 
     } 
     public string LpszProxyBypass 
     { 
      get; set; 
     } 
    } 
    internal string[] GetV(WindowsIdentity windowsIdentity) 
    { 
     string[] settings = new string[] { "", "" }; 
     using (windowsIdentity.Impersonate()) 
     { 

      int bufferLength = 0; 
      IntPtr buffer = IntPtr.Zero; 

      InternetQueryOption(IntPtr.Zero, INTERNET_OPTION_PROXY, IntPtr.Zero, 
           ref bufferLength); 
      try 
      { 
       buffer = Marshal.AllocHGlobal(bufferLength); 
       if (InternetQueryOption(IntPtr.Zero, INTERNET_OPTION_PROXY, buffer, 
             ref bufferLength)) 
       { 
        INTERNET_PROXY_INFO proxyInfo = (INTERNET_PROXY_INFO) 
        // Converting structure to IntPtr. 
        Marshal.PtrToStructure(buffer, typeof(INTERNET_PROXY_INFO)); 
        // Getting the proxy details. 
        settings[0] = proxyInfo.LpszProxy.Split(':')[0]; 
        settings[1] = proxyInfo.LpszProxy.Split(':')[1]; 
       } 
      } 
      catch { } 
     } 
     return settings; 
    } 
} 

Vous devez ajouter le WindowsIdentity de l'utilisateur actuellement connecté et retournera une chaîne [] avec [0] = proxystring & [1] = port proxy. Ce qui suit fonctionne bien comme un service:

  WebClient wClient = new WebClient(); 
      wClient.Proxy = new WebProxy(GetProxySettings.GetV(GetWindowsIdentity())[0],GetProxySettings.GetV(GetWindowsIdentity())[1]); 
      string xx = wClient.DownloadString(@"https://www.dropbox.com");