使用C#从Windows凭据存储中检索凭据

时间:2013-07-19 08:26:52

标签: c# credentials

我只想查询凭据存储(或Win8中调用的Vault)并获取登录数据。在这种情况下,MSDN真的没有用,我也不想要任何C ++ pInvoke方法。

我知道这里曾经问过几次类似的问题,但这些解决方案都不适用于我的情况。我不使用Metro App编程,因此PasswordVault之类的东西(因为它看起来)不可用。我只是创建一个简单的C#WPF桌面应用程序。

理想情况下,它应该适用于多个Windows版本,但首选Win8。

更具体地说,我想查询来自CRM插件的存储数据,以便自动让我的应用程序登录到CRM服务器,而无需用户请求他的凭证。这意味着,如果这是可能的......

那么如何访问Windows凭据存储?

4 个答案:

答案 0 :(得分:41)

我一直在使用一个名为CredentialManagement的Nuget库 http://nuget.org/packages/CredentialManagement/

用法非常简单。我把它包裹了一点,但可能不需要:

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

样本用法:

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

如果您有兴趣自己实施,请浏览来源: http://credentialmanagement.codeplex.com/SourceControl/latest

诀窍是Credential Manager中没有C#API。 这个库很好地包装了其他.dll入口点。 : - )

答案 1 :(得分:4)

这适用于Windows 2k12,我没有Win 8机箱可供测试

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

简而言之

  1. 卸载项目文件
  2. 编辑
  3. 添加< TargetPlatformVersion> 8.0< / TargetPlatformVersion>到PropertyGroup部分
  4. 添加对Windows.Security的引用(您将拥有Windows库列表)
  5. 添加位于C:\ Program Files(x86)\ Reference Assemblies \ Microsoft \ Framework.NETCore \ v4.5
  6. 中的System.Runtime.WindowsRuntime.dll

    然后您可以使用此功能(来自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;
    }
    

答案 2 :(得分:3)

Randy的回答使用System.String来存储密码,这是不安全的。您将需要System.Security.SecureString用于此目的。

如果您只是阅读Credential Management with the .NET Framework 2.0,那会更好。

答案 3 :(得分:0)

使用CredentialManagement(查看答案https://stackoverflow.com/a/17747020/206730)。

使用Powershell也许有用:

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

我无法列出存储的所有凭据。

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

    }