web-dev-qa-db-fra.com

Récupérer des informations d'identification à partir du magasin d'informations d'identification Windows à l'aide de C #

Je veux simplement interroger la banque d'informations d'identification (ou le coffre-fort comme il est appelé dans Win8) et obtenir les données de connexion. Le MSDN est vraiment inutile dans ce cas et je ne veux pas non plus d’approches p ++ invocation C++.

Je sais que des questions similaires ont été posées ici à quelques reprises, mais aucune de ces solutions ne fonctionne dans mon cas. Je n'utilise pas la programmation Metro App, des éléments tels que PasswordVault ne sont donc pas disponibles. Je viens de créer une simple application de bureau C # WPF.

Idéalement, cela devrait fonctionner dans plusieurs versions de Windows, mais Win8 est préférable.

Plus précisément, je souhaite interroger les données stockées à partir du plug-in CRM pour Outlook afin que mon application se connecte automatiquement au serveur CRM sans que l'utilisateur ne demande ses informations d'identification. Cela signifie, si cela est même possible ...

Alors, comment puis-je accéder au Windows Credentials Store?

24
Kirschi

J'utilise une bibliothèque Nuget appelée CredentialManagement http://nuget.org/packages/CredentialManagement/

L'utilisation est assez simple. Je l'ai enveloppé un peu, mais je n'avais probablement pas besoin de:

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();
    }
}

Exemple d'utilisation:

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);

Si vous êtes intéressé par sa mise en oeuvre, parcourez la source: http://credentialmanagement.codeplex.com/SourceControl/latest

Le truc, c’est qu’il n’ya pas d’API C # dans Credential Manager . Cette bibliothèque encapsule bien les autres points d’entrée .dll. :-)

39
Randy James

Cela fonctionne à partir de Windows 2k12, je n'ai pas de boîte Win 8 pour tester

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

En bref

  1. Décharger le fichier de projet
  2. Éditer
  3. Ajoutez <TargetPlatformVersion> 8.0 </ TargetPlatformVersion> à la partie PropertyGroup
  4. Ajouter une référence à Windows.Security (vous aurez une liste de bibliothèques Windows)
  5. Ajouter System.Runtime.WindowsRuntime.dll situé dans C:\Program Files (x86)\Assemblys de référence\Microsoft\Framework.NETCore\v4.5

Vous pouvez ensuite utiliser ceci (depuis ici ):

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;
}
4
L1011

La réponse de Randy utilise System.String pour stocker le mot de passe, ce qui est dangereux. Vous voudrez utiliser System.Security.SecureString à cette fin.

Vous feriez mieux de lire Gestion des informations d'identification avec le .NET Framework 2.0 .

3
user1735022

Utilisation de CredentialManagement (voir la réponse https://stackoverflow.com/a/17747020/206730 ).

Peut-être utile d’utiliser Powershell aussi: 

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

Je ne peux pas répertorier toutes les informations d'identification stockées.

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;
        }

    }
0
Kiquenet