web-dev-qa-db-ja.com

C#を使用してWindows資格情報ストアから資格情報を取得する

認証情報ストア(またはVaultがWindows 8で呼び出されるため)にクエリを実行して、ログインデータを取得するだけです。この場合、MSDNは本当に役に立ちません。また、C++ P/Invoke アプローチも必要ありません。

同様の質問がここで何度か行われたことは知っていますが、これらの解決策はどれも私の場合はうまくいきません。私はMetro Appプログラミングを使用していないので、PasswordVaultのようなもの(見たところ)は利用できません。単純なC#WPFデスクトップアプリケーションを作成するだけです。

理想的には、いくつかのWindowsバージョンで動作するはずですが、Windows 8が推奨されます。

具体的には、Outlook用CRMプラグインから格納されたデータをクエリして、ユーザーに資格情報を要求することなく、アプリケーションがCRMサーバーに自動的にログインするようにします。つまり、これが可能であれば...

では、どうすればWindows資格情報ストアにアクセスできますか?

37
Kirschi

CredentialManagement と呼ばれる、私が使用してきたNuGetライブラリがあります。

使い方はかなり簡単です。少し折り返しましたが、おそらく以下のことは必要なかったでしょう:

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エントリポイントを適切にラップします。 :-)

47
Randy James

これは Windows Server 2012 から機能します。テスト用のWindows 8ボックスがありません。

。NETデスクトップアプリケーションでのWindows 8 WinRT APIの使用

要するに

  1. プロジェクトファイルをアンロード
  2. それを編集する
  3. <TargetPlatformVersion> 8.0 </ TargetPlatformVersion>をPropertyGroupパーツに追加します
  4. Windows.Securityへの参照を追加します(Windowsライブラリのリストが表示されます)。
  5. C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5にある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;
}
4
L1011

ランディからの答えはSystem.Stringパスワードを保存するため、安全ではありません。 System.Security.SecureString その目的のために。

。NET Framework 2.0による資格情報の管理 を読んだ方がよいでしょう。

3
user1735022

CredentialManagementを使用する(回答を表示 C#を使用してWindows資格情報ストアから資格情報を取得する )。

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