通过


适用于 Windows 应用的凭据保险箱

本文介绍了 Windows 应用可如何使用凭据保险箱安全存储和检索用户凭据,并使用用户的 Microsoft 帐户在设备间漫游用户凭据。

用于凭据保险箱访问的 Windows 运行时 (WinRT) API 是 Windows 软件开发工具包 (SDK)一部分。 这些 API 可用于 WinUI 和其他桌面应用,例如 WPF 和 WinForms。 有关在 Windows 桌面应用中使用 WinRT API 的详细信息,请参阅在桌面应用中调用Windows 运行时 API。

示例方案的概述

例如,你有一个连接到服务以访问受保护资源(如媒体文件或社交网络)的应用。 你的服务需要每位用户的登录信息。 你已将 UI 内置到应用中,用于获取用户的用户名和密码,然后使用该 UI 将用户登录到服务中。 使用保险箱 API 可为用户存储用户名和密码,并在他们下次打开应用时轻松地检索它们并自动使用户登录(不论他们在什么设备上)。

存储在凭据保险箱中的用户凭据不会过期,也不受ApplicationData.RoamingStorageQuota的影响,并且不会因不活动而像传统漫游数据一样被清除。 但是,在凭据保险箱中,每个应用最多只能存储 20 个凭据。

凭据保险箱对于域帐户的工作方式略有不同。 如果某些凭据与您的 Microsoft 帐户一起存储,并且您将该帐户与域帐户关联(例如您在工作中使用的帐户),那么这些凭据将会漫游到该域帐户。 但是,任何在使用域帐户登录时添加的新凭据将无法漫游。 这可确保域的专用凭据不会在域外部公开。

存储用户凭据

  1. 使用来自 Windows.Security.Credentials 命名空间的 PasswordVault 对象获取对凭据保险箱的引用。
  2. 创建包含你的应用的标识符、用户名和密码的 PasswordCredential 对象,并将该对象传递至 PasswordVault.Add 方法以将凭据添加到保险箱。
var vault = new Windows.Security.Credentials.PasswordVault();
vault.Add(new Windows.Security.Credentials.PasswordCredential(
    "My App", username, password));

检索用户凭据

在你拥有对 PasswordVault 对象的引用之后,你有多个选项从凭据保险箱检索用户凭据。

让我们来查看一个示例,在此示例中我们已在一个应用中全局存储了资源名,并且,如果找到了它们的凭据,我们将使用户自动登录。 如果我们找到了同一个用户的多个凭据,我们将要求用户选择一个默认凭据以在登录时使用。

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

删除用户凭据

在凭据保险箱中删除用户凭据是一个快捷的两步式过程。

  1. 使用 PasswordVault 对象从 Windows.Security.Credentials 命名空间获取对凭据保险箱的引用。
  2. 将希望删除的凭据传递至 PasswordVault.Remove 方法。
var vault = new Windows.Security.Credentials.PasswordVault();
vault.Remove(new Windows.Security.Credentials.PasswordCredential(
    "My App", username, password));

最佳实践

将凭据保险箱仅用于存储密码,不要将其用于存储较大的数据块。

仅当满足以下条件时才将密码保存在凭据保险箱中:

  • 用户已成功登录。
  • 用户已选择保存密码。

永远不要使用应用数据或漫游设置在纯文本中存储凭据。