使用C#从Windows凭据存储检索凭据
本文关键字:检索 存储 Windows 使用 | 更新日期: 2023-09-27 18:23:49
我只想查询凭据存储(或Windows 8中的Vault)并获取登录数据。MSDN在这种情况下确实没有帮助,而且我也不想要任何C++P/Invoke方法。
我知道类似的问题在这里已经被问过几次了,但这些解决方案都不适用于我的情况。我不使用Metro应用程序编程,所以像PasswordVault
这样的东西(看起来)不可用。我只是创建了一个简单的C#WPF桌面应用程序。
理想情况下,它应该在几个Windows版本中工作,但Windows;8是优选的。
更具体地说,我想从Outlook的CRM插件中查询存储的数据,以自动让我的应用程序登录到CRM服务器,而无需用户询问他/她的凭据。这意味着,如果这是可能的。。。
那么,我如何访问Windows凭据存储?
我一直在使用一个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
技巧是没有进入凭证管理器的C#API。这个库很好地封装了其他.dll入口点。:-)
这可以在Windows Server 2012上运行。我没有Windows;8个测试框。
在.NET桌面应用程序中使用Windows 8 WinRT API
简而言之,
- 卸载项目文件
- 编辑它
- 添加<TargetPlatformVersion>8.0<TargetPlatformVersion>到PropertyGroup部分
- 添加对Windows.Security的引用(您将获得Windows库的列表)
- 添加位于
C:'Program Files (x86)'Reference Assemblies'Microsoft'Framework'.NETCore'v4.5
中的System.Runtime.WindowsRuntime.dll
然后你可以使用这个(从这里):
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的凭据管理,您会过得更好。
使用凭据管理(查看答案使用C#从Windows凭据存储中检索凭据)。
使用PowerShell也可能有用:
CredMan.ps1https://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;
}
}