Получить учетные данные из хранилища учетных данных Windows с помощью С#
Я просто хочу запросить хранилище учетных данных (или Vault, как его называют в Windows 8) и получить данные для входа. MSDN действительно бесполезен в этом случае, и я также не хочу никаких подходов C++ P/Invoke.
Я знаю, что подобные вопросы задавались здесь несколько раз, но ни одно из этих решений не работает в моем случае. Я не использую программирование приложений Metro, поэтому такие вещи, как PasswordVault
(как это выглядит) недоступны. Я просто создаю простое настольное приложение С# WPF.
В идеале он должен работать в нескольких версиях Windows, но Windows 8 предпочтительнее.
Точнее говоря, я хочу запросить сохраненные данные из плагина CRM для Outlook, чтобы мое приложение автоматически входило на сервер CRM, не запрашивая у пользователя свои учетные данные. Это значит, если это вообще возможно...
Итак, как мне получить доступ к хранилищу учетных данных Windows?
Ответы
Ответ 1
Я использую библиотеку NuGet, которая называется 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
Хитрость в том, что в диспетчере учетных данных отсутствует API С#. Эта библиотека красиво оборачивает другие точки входа .dll. :-)
Ответ 2
Это работает с Windows Server 2012. У меня нет Windows 8 для тестирования.
Использование Windows 8 WinRT API в настольных приложениях .NET
Короче
- Выгрузить файл проекта
- Редактировать это
- Добавьте <TargetPlatformVersion> 8.0 </TargetPlatformVersion> в часть PropertyGroup.
- Добавьте ссылку на Windows.Security (у вас будет список библиотек Windows)
- Добавьте
System.Runtime.WindowsRuntime.dll
расположенный в C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5
Затем вы можете использовать это (отсюда):
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 doesnt
// exist, then display UI to have the user select
// a default username.
defaultUserName = GetDefaultUserNameUI();
credential = vault.Retrieve(resourceName, defaultUserName);
}
}
return credential;
}
Ответ 3
Ответ от Randy использует System.String
для хранения пароля, что небезопасно. Для этой цели вы захотите использовать System.Security.SecureString
.
Вам было бы лучше, если бы вы просто прочитали Управление учетными данными с .NET Framework 2.0.
Ответ 4
Использование CredentialManagement (просмотреть ответ Получить учетные данные из хранилища учетных данных 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;
}
}