本文介绍了 Windows 应用可如何使用凭据保险箱安全存储和检索用户凭据,并使用用户的 Microsoft 帐户在设备间漫游用户凭据。
用于凭据保险箱访问的 Windows 运行时 (WinRT) API 是 Windows 软件开发工具包 (SDK) 的一部分。 这些 API 可用于 WinUI 和其他桌面应用,例如 WPF 和 WinForms。 有关在 Windows 桌面应用中使用 WinRT API 的详细信息,请参阅在桌面应用中调用Windows 运行时 API。
示例方案的概述
例如,你有一个连接到服务以访问受保护资源(如媒体文件或社交网络)的应用。 你的服务需要每位用户的登录信息。 你已将 UI 内置到应用中,用于获取用户的用户名和密码,然后使用该 UI 将用户登录到服务中。 使用保险箱 API 可为用户存储用户名和密码,并在他们下次打开应用时轻松地检索它们并自动使用户登录(不论他们在什么设备上)。
存储在凭据保险箱中的用户凭据不会过期,也不受ApplicationData.RoamingStorageQuota的影响,并且不会因不活动而像传统漫游数据一样被清除。 但是,在凭据保险箱中,每个应用最多只能存储 20 个凭据。
凭据保险箱对于域帐户的工作方式略有不同。 如果某些凭据与您的 Microsoft 帐户一起存储,并且您将该帐户与域帐户关联(例如您在工作中使用的帐户),那么这些凭据将会漫游到该域帐户。 但是,任何在使用域帐户登录时添加的新凭据将无法漫游。 这可确保域的专用凭据不会在域外部公开。
存储用户凭据
- 使用来自 Windows.Security.Credentials 命名空间的 PasswordVault 对象获取对凭据保险箱的引用。
- 创建包含你的应用的标识符、用户名和密码的 PasswordCredential 对象,并将该对象传递至 PasswordVault.Add 方法以将凭据添加到保险箱。
var vault = new Windows.Security.Credentials.PasswordVault();
vault.Add(new Windows.Security.Credentials.PasswordCredential(
"My App", username, password));
检索用户凭据
在你拥有对 PasswordVault 对象的引用之后,你有多个选项从凭据保险箱检索用户凭据。
- 你可以使用 PasswordVault.RetrieveAll 方法从保险箱检索用户为你的应用提供的所有凭据。
- 如果你知道存储的凭据的用户名,你可以使用 PasswordVault.FindAllByUserName 方法检索该用户名的所有凭据。
- 如果你知道存储的凭据的资源名,你可以使用 PasswordVault.FindAllByResource 方法检索该资源名的所有凭据。
- 最后,如果你同时知道一个凭据的用户名和资源名,你可以使用 PasswordVault.Retrieve 方法仅检索该凭据。
让我们来查看一个示例,在此示例中我们已在一个应用中全局存储了资源名,并且,如果找到了它们的凭据,我们将使用户自动登录。 如果我们找到了同一个用户的多个凭据,我们将要求用户选择一个默认凭据以在登录时使用。
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();
IReadOnlyList<PasswordCredential> credentialList = null;
try
{
credentialList = vault.FindAllByResource(resourceName);
}
catch(Exception)
{
return null;
}
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;
}
删除用户凭据
在凭据保险箱中删除用户凭据是一个快捷的两步式过程。
- 使用 PasswordVault 对象从 Windows.Security.Credentials 命名空间获取对凭据保险箱的引用。
- 将希望删除的凭据传递至 PasswordVault.Remove 方法。
var vault = new Windows.Security.Credentials.PasswordVault();
vault.Remove(new Windows.Security.Credentials.PasswordCredential(
"My App", username, password));
最佳实践
将凭据保险箱仅用于存储密码,不要将其用于存储较大的数据块。
仅当满足以下条件时才将密码保存在凭据保险箱中:
- 用户已成功登录。
- 用户已选择保存密码。
永远不要使用应用数据或漫游设置在纯文本中存储凭据。