到目前为止,为了在 .NET 应用程序中存储和检索机密(如凭据),我成功地在 Windows 上使用了CredentialManagement包。现在我想跨平台。
所以我需要从 .NET Core 跨平台应用程序访问Windows 凭据管理器。如果它在 Windows 上运行 - 使用凭据管理器。如果它在 Linux 上运行 - 不要崩溃(使用钥匙链或其他任何东西,这是下一步)。
这将如何完成?
(注意:我对 Windows 凭据管理器的替代品持开放态度,但它们应该提供同等级别的保护。)
到目前为止,为了在 .NET 应用程序中存储和检索机密(如凭据),我成功地在 Windows 上使用了CredentialManagement包。现在我想跨平台。
所以我需要从 .NET Core 跨平台应用程序访问Windows 凭据管理器。如果它在 Windows 上运行 - 使用凭据管理器。如果它在 Linux 上运行 - 不要崩溃(使用钥匙链或其他任何东西,这是下一步)。
这将如何完成?
(注意:我对 Windows 凭据管理器的替代品持开放态度,但它们应该提供同等级别的保护。)
确定运行应用程序的操作系统。这可以帮助,供参考
windows的完整示例(CredentialManagement + Detect Operating System),
using CredentialManagement;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace DetectOSCredentialManagement
{
class Program
{
static void Main(string[] args)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Console.WriteLine("Hello Beauty!");
Program.SetCredentials("FOO", "friday", "fr!d@y0", PersistanceType.LocalComputer);
var userpass = Program.GetCredential("FOO");
Console.WriteLine($"User: {userpass.Username} Password: {userpass.Password}");
Program.RemoveCredentials("FOO");
Debug.Assert(Program.GetCredential("FOO") == null);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Console.WriteLine("Hello Cutie!");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Console.WriteLine("Too Costly!");
}
}
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();
}
}
public class UserPass
{
public string Username { get; set; }
public string Password { get; set; }
public UserPass(string username, string password)
{
Username = username;
Password = password;
}
}
}
System.Security.Permissions
-- 这个 dll 也需要在上面的应用程序中运行。
我最终使用适用于 Windows 的数据保护 API (DPAPI) 将机密存储在已在登录用户范围内加密的文件中。
密码的加密存储:
try
{
var passwordBytes = Encoding.UTF8.GetBytes(password);
var protectedPasswordBytes = ProtectedData.Protect(passwordBytes, null, DataProtectionScope.CurrentUser);
var protectedPasswordBytesBase64 = Convert.ToBase64String(protectedPasswordBytes);
File.WriteAllText(passwordFilePath, protectedPasswordBytesBase64);
} catch (PlatformNotSupportedException)
{
Debug.WriteLine("Could not store credentials");
}
解密:
if (File.Exists(passwordFilePath))
{
var protectedPasswordBytesBase64 = File.ReadAllText(passwordFilePath);
var protectedPasswordBytes = Convert.FromBase64String(protectedPasswordBytesBase64);
var passwordBytes = ProtectedData.Unprotect(protectedPasswordBytes, null, DataProtectionScope.CurrentUser);
password = Encoding.UTF8.GetString(passwordBytes);
}
(仅适用于 Windows,对于其他操作系统,我将使用其他解决方案。)