2013-07-19 18 views
19

Voglio semplicemente interrogare l'archivio di credenziali (o Vault come viene chiamato in Win8) e ottenere i dati di accesso. In questo caso, MSDN non è molto utile e non voglio nemmeno approcci di pInvoke in C++.Recupero delle credenziali dall'archivio delle credenziali di Windows utilizzando C#

So che domande simili sono state poste qui alcune volte, ma nessuna di queste soluzioni funziona nel mio caso. Io non uso la programmazione Metro App, quindi cose come PasswordVault sono (come sembra) non disponibili. Creo semplicemente una semplice applicazione desktop C# WPF.

Idealmente dovrebbe funzionare in diverse versioni di Windows, ma è preferibile Win8.

In particolare, desidero interrogare i dati memorizzati dal plug-in CRM per Outlook affinché la mia app acceda automaticamente al server CRM senza che l'utente chieda le sue credenziali. Ciò significa, se questo è anche possibile ...

Quindi, come posso accedere all'archivio delle credenziali di Windows?

risposta

31

C'è una biblioteca Nuget che ho usato chiamato CredentialManagement http://nuget.org/packages/CredentialManagement/

L'utilizzo è piuttosto semplice. Ho avvolto un po ', ma probabilmente non avevo bisogno di: utilizzo

public static class CredentialUtil 
{ 
    public static UserPass GetCredential(string target) 
    { 
     var cm = new Credential {Target = target}; 
     if (!cm.Load()) 
     { 
      return null; 
     } 

     //UserPass is just a class with two string properties for user and pass 
     return new UserPass(cm.Username, cm.Password); 
    } 

    public static bool SetCredentials(
     string target, string username, string password, PersistanceType persistenceType) 
    { 
     return new Credential {Target = target, Username = username, 
       Password = password, PersistanceType = persistenceType}.Save(); 
    } 

    public static bool RemoveCredentials(string target) 
    { 
     return new Credential { Target = target }.Delete(); 
    } 
} 

Esempio:

CredentialUtil.SetCredentials("FOO", "john", "1234", PersistanceType.LocalComputer); 
var userpass = CredentialUtil.GetCredential("FOO"); 
Console.WriteLine($"User: {userpass.Username} Password: {userpass.Password}"); 
CredentialUtil.RemoveCredentials("FOO"); 
Debug.Assert(CredentialUtil.GetCredential("FOO") == null); 

Se siete interessati ad implementare da soli, sfogliare la fonte: http://credentialmanagement.codeplex.com/SourceControl/latest

Il trucco è che non ci sono API C# in Credential Manager. Questa libreria avvolge bene gli altri punti di accesso .dll. :-)

+0

Quello che non capisco è la classe PasswordVault è segnato dal [DualApiPartition()] attributo che significa che può essere utilizzato anche in applicazioni desktop (WPF). È un errore di battitura nella loro pagina di classe? https://msdn.microsoft.com/en-us/library/windows/apps/windows.security.credentials.passwordvault.aspx – WiteCastle

+2

Ci sono due considerazioni con questa risposta e non sono necessariamente difetti della libreria, ma difetti di il gestore delle credenziali in Windows. In pratica, puoi caricare e decrittografare il nome utente e la password per qualsiasi credenziale sul tuo computer, così come qualsiasi altra applicazione. Questo non è sicuro o protetto da alcun senso della parola. Inoltre, vi è ovviamente l'uso della stringa di testo semplice, come hanno menzionato altri utenti. Tuttavia, il primo punto da solo dovrebbe renderti molto scettico su questo intero sistema. –

+1

Ho trovato questa pagina utile per capire cosa significano cose diverse nella classe Credential: https://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx –

2

La risposta di Randy utilizza System.String per memorizzare la password, che non è sicura. Vorrete usare System.Security.SecureString per quello scopo.

Sarebbe meglio se leggeste semplicemente Credential Management with the .NET Framework 2.0.

+2

Hai ragione e in generale utilizzo SecureString. Ma la pagina MSDN che hai collegato non risponde alla domanda. Risponde solo a come gestire le credenziali/credenziali e le richieste di password, non come gestire il Vault password incorporato in Windows. – Kirschi

3

Questo funziona da un 2k12 di Windows, non ho una scatola Win 8 per testare da

http://blogs.msdn.com/b/cdndevs/archive/2013/10/02/using-windows-8-winrt-apis-in-net-desktop-applications.aspx

Insomma

  1. file di progetto di scaricamento
  2. Edit è
  3. Aggiungi < TargetPlatformVersion> 8.0 </TargetPlatformVersion> alla parte PropertyGroup
  4. Aggiungere riferimento a Windows.Security (verrà visualizzato un elenco di librerie di Windows)
  5. Aggiungi System.Runtime.WindowsRuntime.dll situato in C: \ Programmi (x86) \ Assiemi di riferimento \ Microsoft \ Framework.NETCore \ v4.5

È quindi possibile utilizzare questo (da here):

private string resourceName = "My App"; 
private string defaultUserName; 

private void Login() 
{ 
var loginCredential = GetCredentialFromLocker(); 

if (loginCredential != null) 
{ 
    // There is a credential stored in the locker. 
    // Populate the Password property of the credential 
    // for automatic login. 
    loginCredential.RetrievePassword(); 
} 
else 
{ 
    // There is no credential stored in the locker. 
    // Display UI to get user credentials. 
    loginCredential = GetLoginCredentialUI(); 
} 

// Log the user in. 
ServerLogin(loginCredential.UserName, loginCredential.Password); 
} 


private Windows.Security.Credentials.PasswordCredential GetCredentialFromLocker() 
{ 
Windows.Security.Credentials.PasswordCredential credential = null; 

var vault = new Windows.Security.Credentials.PasswordVault(); 
var credentialList = vault.FindAllByResource(resourceName); 
if (credentialList.Count > 0) 
{ 
    if (credentialList.Count == 1) 
    { 
     credential = credentialList[0]; 
    } 
    else 
    { 
     // When there are multiple usernames, 
     // retrieve the default username. If one doesn’t 
     // exist, then display UI to have the user select 
     // a default username. 

     defaultUserName = GetDefaultUserNameUI(); 

     credential = vault.Retrieve(resourceName, defaultUserName); 
    } 
} 

return credential; 
} 
0

Utilizzando CredentialManagement (vista la risposta https://stackoverflow.com/a/17747020/206730).

Forse utile utilizzando PowerShell troppo:

CredMan.ps1
https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Credentials-d44c3cde

non posso elencare tutte le credenziali memorizzate.

using CredentialManagement; 
using System.Diagnostics; 

namespace UnitTestProject1 
{ 
    [TestClass] 
    public class CredentialTests 
    { 

     [TestMethod] 
     public void Set_Credentials_for_older_domain_whe_migration_to_new_domain() 
     { 
      var accesos = new List<string> { 
      "intranet", 
      "intranet.xxxxx.net", 
      "intranet.zzzzzzzz.com", 
      "intranetescritorio.zzzzzzzz.net", 
      "more...", 
      }; 

      accesos.ForEach(acceso => SaveCredential(acceso)); 
     } 

     private static Credential SaveCredential(string CredentialName) 
     { 
      var UserName = @"OLDERDOMAIN\user"; 
      var Password = "pass"; 

      var cm = new Credential { Target = CredentialName, Type = CredentialType.DomainPassword }; 
      if (cm.Exists()) 
      { 
       cm.Load(); 
       Console.WriteLine("Credential " + cm.Target + ". Data: " + cm.Username + " " + cm.Password); 

       //if (cm.Type == CredentialType.Generic) cm.Delete(); 

       return cm; 
      } 

      cm = new Credential 
      { 
       Target = CredentialName, 
       Type = CredentialType.DomainPassword, 
       PersistanceType = PersistanceType.Enterprise, 
       Username = UserName, 
       Password = Password 
      }; 
      cm.Save(); 
      return cm; 
     } 

    } 
Problemi correlati