認証情報ストア(またはVaultがWindows 8で呼び出されるため)にクエリを実行して、ログインデータを取得するだけです。この場合、MSDNは本当に役に立ちません。また、C++ P/Invoke アプローチも必要ありません。
同様の質問がここで何度か行われたことは知っていますが、これらの解決策はどれも私の場合はうまくいきません。私はMetro Appプログラミングを使用していないので、PasswordVault
のようなもの(見たところ)は利用できません。単純なC#WPFデスクトップアプリケーションを作成するだけです。
理想的には、いくつかのWindowsバージョンで動作するはずですが、Windows 8が推奨されます。
具体的には、Outlook用CRMプラグインから格納されたデータをクエリして、ユーザーに資格情報を要求することなく、アプリケーションがCRMサーバーに自動的にログインするようにします。つまり、これが可能であれば...
では、どうすればWindows資格情報ストアにアクセスできますか?
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エントリポイントを適切にラップします。 :-)
これは Windows Server 2012 から機能します。テスト用のWindows 8ボックスがありません。
。NETデスクトップアプリケーションでのWindows 8 WinRT APIの使用
要するに
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;
}
ランディからの答えはSystem.String
パスワードを保存するため、安全ではありません。 System.Security.SecureString
その目的のために。
。NET Framework 2.0による資格情報の管理 を読んだ方がよいでしょう。
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;
}
}