UWP应用中如何为PasswordCredential存储或关联额外数据?
解决UWP多账户额外信息安全漫游存储的方案
你提到Credential Locker能安全存储用户名密码且支持漫游,但没法直接存URL、开发者密钥这类额外信息,结合你的需求,我推荐Credential Locker + 加密后的漫游设置的组合方案,既利用Credential Locker的安全漫游特性,又能妥善存储额外信息,具体实现如下:
核心思路
- 用Credential Locker存储每个账户的核心凭据(用户名、密码),给每个账户分配一个唯一标识ID作为Credential的
Resource字段,用来关联后续的额外信息。 - 将URL、开发者密钥等额外信息序列化后,用Windows自带的数据保护API加密(确保只有当前用户可解密),再存储到
RoamingSettings中,用同一个唯一标识ID作为键,实现与Credential的关联。 - 两者都支持随用户Microsoft账户漫游,完美匹配你的需求。
具体实现步骤
1. 生成账户唯一标识ID
为了确保每个账户的Credential和额外信息能准确关联,我们可以用URL+用户名的组合生成唯一哈希ID,避免重复:
using System.Security.Cryptography; using System.Text; public string GenerateAccountUniqueId(string accountUrl, string username) { // 组合URL和用户名作为哈希输入 string input = $"{accountUrl}_{username}"; using (SHA256 sha256Hash = SHA256.Create()) { byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); // 转换为安全的Base64字符串(替换特殊字符) return Convert.ToBase64String(bytes).Replace('/', '_').Replace('+', '-'); } }
2. 存储凭据到Credential Locker
利用PasswordVault存储用户名和密码,唯一ID作为Resource参数:
using Windows.Security.Credentials; public void StoreAccountCredential(string uniqueId, string username, string password) { var passwordVault = new PasswordVault(); // 创建凭据对象,Resource用唯一ID,确保每个账户唯一 var credential = new PasswordCredential(uniqueId, username, password); // 添加到Vault passwordVault.Add(credential); }
3. 加密并存储额外信息到RoamingSettings
先把额外信息序列化为JSON,再用DataProtectionProvider加密(限定当前用户访问),最后存入漫游设置:
using Windows.Security.Cryptography; using Windows.Security.Cryptography.DataProtection; using Windows.Storage; using System.Text.Json; // 定义额外信息的实体类 public class AccountExtraInfo { public string ServiceUrl { get; set; } public string DeveloperKey { get; set; } // 可根据需求添加其他字段,比如备注、过期时间等 } public async Task StoreAccountExtraInfo(string uniqueId, AccountExtraInfo extraInfo) { // 1. 序列化额外信息为JSON字符串 string jsonContent = JsonSerializer.Serialize(extraInfo); // 2. 转换为二进制数据 IBuffer dataBuffer = CryptographicBuffer.ConvertStringToBinary(jsonContent, BinaryStringEncoding.Utf8); // 3. 创建数据保护提供者,限定只有当前用户能解密 var protectionProvider = new DataProtectionProvider("LOCAL=user"); // 4. 加密数据 IBuffer encryptedBuffer = await protectionProvider.ProtectAsync(dataBuffer); // 5. 转换为Base64字符串存储到漫游设置 string encryptedContent = CryptographicBuffer.EncodeToBase64String(encryptedBuffer); ApplicationData.Current.RoamingSettings.Values[uniqueId] = encryptedContent; }
4. 读取账户信息
从Credential Locker取出凭据,同时从RoamingSettings取出加密的额外信息并解密:
using Windows.Security.Credentials; using Windows.Security.Cryptography; using Windows.Security.Cryptography.DataProtection; using Windows.Storage; using System.Text.Json; public async Task<(PasswordCredential Credential, AccountExtraInfo ExtraInfo)> GetAccountInfo(string uniqueId) { // 1. 从Credential Locker读取凭据 var passwordVault = new PasswordVault(); PasswordCredential credential = null; try { // 根据唯一ID(Resource)筛选凭据 var credentials = passwordVault.RetrieveAll().Where(c => c.Resource == uniqueId); credential = credentials.FirstOrDefault(); if (credential != null) { credential.RetrievePassword(); // 取出密码(默认不加载) } } catch (Exception ex) { // 处理凭据不存在的异常 return (null, null); } // 2. 读取并解密额外信息 AccountExtraInfo extraInfo = null; if (ApplicationData.Current.RoamingSettings.Values.TryGetValue(uniqueId, out object encryptedObj)) { string encryptedContent = encryptedObj.ToString(); IBuffer encryptedBuffer = CryptographicBuffer.DecodeFromBase64String(encryptedContent); var protectionProvider = new DataProtectionProvider(); IBuffer decryptedBuffer = await protectionProvider.UnprotectAsync(encryptedBuffer); string jsonContent = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, decryptedBuffer); extraInfo = JsonSerializer.Deserialize<AccountExtraInfo>(jsonContent); } return (credential, extraInfo); }
关键注意事项
- 漫游限制:RoamingSettings有默认100KB的同步配额,如果你的额外信息较多,要注意控制单条数据大小,避免无法同步。
- 安全性:
DataProtectionProvider的LOCAL=user范围确保加密后的数据只有当前Windows用户能解密,即使漫游到其他设备,也需要同一个Microsoft账户登录才能访问。 - 错误处理:实际使用中要添加异常捕获,比如凭据不存在、解密失败、漫游设置读取失败等场景。
- Credential Locker限制:你提到能接受10个凭据的限制,这个方案不会增加Credential的数量,每个账户对应一个Credential,完全符合你的要求。
内容的提问来源于stack exchange,提问作者ATL_DEV
相关产品推荐
相关产品推荐

