• .NET Core程序中使用User Secrets存储敏感数据


    前言

    在开发中经常会用到一些敏感数据,比如AppSecret或数据库连接字符串,无论是硬编码还是写在配置文件中,最终都要push到svn或git上。对于开源项目,这些敏感数据就无隐私可言了,对于私有项目,一旦源代码管理服务器被黑,这些敏感数据也将暴露无遗。所以,最佳实践就是不要将敏感数据写到源代码中。

    以往我们常常将数据库连接字符串写在web.config中,.NET Core中写在appsettings.json中,开发环境下如果一个开发者修改了连接字符串,为了不影响其他开发者,每次提交代码的时候就应该忽略该配置文件,如果还添加了其他配置,必须提交的话,要么先撤销连接字符串的修改再提交,要么直接提交会影响其他开发人员。很多时候,我们就是直接提交了,大不了其他开发者pull下来代码再修改一下。但是,最佳实践就是不要写在配置文件中。

    注意,上面提到的问题都是在开发环境下。

    Secret Manager

    .NET Core中为我们提供了叫Secret Manager的工具,可以实现上文中的最佳实践,再次强调一次,Secret Manager只适用于开发环境中。

    下面说一下Secret Manager,它帮我们抽象了一些细节,比如数据存储在哪以及如何存储的问题。简单来说它帮助我们将数据以明文的形式存在了本地的一个json文件中。系统不同存储的位置也不一样。

    Windows

    %APPDATA%microsoftUserSecrets<userSecretsId>secrets.json
    

    Linux

    ~/.microsoft/usersecrets/<userSecretsId>/secrets.json
    

    Mac

    ~/.microsoft/usersecrets/<userSecretsId>/secrets.json
    

    userSecretsId是在.csproj文件中指定的,会在下文讲到。

    安装、使用

    配置User Secrets及访问需要用到两个包,分别为

    Microsoft.Extensions.SecretManager.Tools
    
    Microsoft.Extensions.Configuration.UserSecrets
    

    简单说一下两者的作用,第一个是工具包,可以使用dotnet user-secrets命令将数据存储到json文件中,第二个包可以通过.NET Core的配置系统访问存储在json文件中的数据。

    dotnet user-secrets -h
    

    这个命令可以查看Secret Manager的用法。

    它有4个命令

    命令 描述 语法
    clear 删除程序中所有的secrets dotnet user-secrets clear
    list 列举程序中所有的secrets dotnet user-secrets list
    remove 删除指定的secret dotnet user-secrets remove NameOfSecret
    set 设置secret dotnet user-secrets set NameOfSecret ValueOfSecret

    以Mac上举例,上面的命令都是操作~/.microsoft/usersecrets/<userSecretsId>/secrets.json这个文件,userSecretsId指定了是哪个项目的secrets。

    userSecretsId在.csproj文件中指定。

    <PropertyGroup>
      <UserSecretsId>userSecretsId的值</UserSecretsId>
    </PropertyGroup>
    

    在mac或linux上,userSecretsId的值可以通过uuidgen生成。

    在Microsoft.Extensions.Configuration.UserSecrets包扩展了ConfigurationBuilder,包含一个AddUserSecrets的扩展方法。如果想通过Configuration访问User Secrets只需要在调用build.AddUserSecrets()即可。

    if (env.IsDevelopment())
    {
        // 搜索包含类型Startup的程序集添加User Secrets的配置源,Startup也可以换成其他程序集中的其他类型
        builder.AddUserSecrets<Startup>();
    }
    

    或干脆直接指定userSecretsId

    if(env.IsDevelopment())
    {
        builder.AddUserSecrets("UserSecretsId");
    }
    

    然后就可以通过Configuration["NameOfSecret"]访问到User Secret了。

    项目实践

    下面通过一个控制台程序演示。

    1. mkdir user-secrets && cd user-secrets # 新建一个目录
    2. dotnet new console # 创建一个控制台应用
    3. dotnet restore # 还原包
    4. dotnet add package Microsoft.Extensions.Configuration.UserSecrets -v 1.1.2 # 安装包
    5. code . # 使用Visual Studio Code打开
    6. 在user-secrets.csproj中添加UserSecretsId
    <PropertyGroup>
        <UserSecretsId>3BF2D901-89B9-437D-8856-CCA63D4606F7</UserSecretsId>
    </PropertyGroup>
    

    以及SecretManager工具包

    <ItemGroup>
        <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="1.0.1" />
    </ItemGroup>
    
    1. dotnet user-secrets set AppKey 12345 # 添加名为AppKey的Secret
    2. 为了判断是在开发环境中,需要添加环境变量,因此需要再安装一个包
      dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables -v 1.1.2
    3. 打开Program.cs,加入以下代码
        class Program
        {
            public static IConfigurationRoot Configuration { get; set; }
            static void Main(string[] args)
            {
                 var builder = new ConfigurationBuilder()
                .AddEnvironmentVariables();
    
                var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
                if (environment == "Development")
                {
                    builder.AddUserSecrets<Program>();
                }
                Configuration = builder.Build();
    
                Console.WriteLine(Configuration["AppKey"]);
            }
        }
    
    1. 运行
      ASPNETCORE_ENVIRONMENT=Development dotnet run

      export ASPNETCORE_ENVIRONMENT=Development
      dotnet run

    ASP.NET Core类似,这里就不再演示了。

    有关.NET Core中User Secrets存储敏感数据的内容,本文就讲这些,如果您觉得对你有所帮助,请“点赞”支持一下,或者关注公众号“chengxulvtu",谢谢!

  • 相关阅读:
    [2012山东ACM省赛] Fruit Ninja II (三重积分,椭球体积)
    [2012山东ACM省赛] The Best Seat in ACM Contest (模拟)
    [2012山东ACM省赛] n a^o7 !(模拟,字符替换)
    [ACM] Hrbustoj 1376 能量项链 (区间动态规划)
    红黑树 c++ 实现
    八大排序算法
    git 常用命令
    linux 学习笔记 day1
    挑战:数据提取 — 实验楼
    挑战:历史命令 — 实验楼
  • 原文地址:https://www.cnblogs.com/nianming/p/7068253.html
Copyright © 2020-2023  润新知