.NET Core:如果 运行 on Windows 如何访问 Windows 凭据管理器(否则忽略)?

.NET Core: How to access Windows Credential Manager if running on Windows (otherwise ignore)?

到目前为止,为了在 .NET 应用程序中存储和检索机密(如凭据),我在 Windows 上成功使用了 CredentialManagement 包。现在我想跨平台。

所以我需要从 .NET Core 跨平台应用程序访问 Windows Credential Manager。如果它在 Windows 上是 运行 - 使用凭据管理器。如果它在 Linux 上是 运行 - 不要崩溃(使用钥匙链或其他任何东西,这是下一步)。

如何做到这一点?

(注意:我对 Windows Credential Manager 的替代方案持开放态度,但它们应该提供同等级别的保护。)

确定您的应用程序所在的操作系统 运行ning。这个有帮助,供参考

  1. RuntimeInformation.IsOSPlatform(OSPlatform) Method
  2. OSPlatform.Windows Property

windows(CredentialManagement + 检测操作系统)的完整示例,

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也需要运行上面的application.

我最终使用 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,对于其他操作系统,我将使用其他解决方案。)