前言

在应用程序开发的过程中,有的时候需要在代码中保存一些机密的信息,比如微信appkey, 连接字符串,加密密钥,字符串,或者是用户名密码等。通常的做法是保存到一个配置文件中,例如 appsettings.json, 以之前文章"Blazor组件自做五: 使用JS隔离封装Google地图" 为例 ,其中有一段代码

@inject IConfiguration config

[Parameter]
public string? Key { get; set; } key = Key ?? config["GoogleKey"];

意思是在 IConfiguration 服务获取 "GoogleKey" , 默认在 appsettings.json 文件配置. 问题就来了,如果我们在工程的 appsettings.json 文件明文保存 GoogleKey , 多人开发或者开源同步到Github/码云上,那肯定是极其不安全的.

严重建议勿在源代码中存储密码或其他敏感数据。 也不要将生产机密用于开发或测试。 机密不随应用一起部署。

用户机密介绍

使用用户机密的场景:

需要保存一些和第三方网站对接的密钥,比如和 微信,微博站点使用的 appkey
给每个开发人员配置不用的用户名密码来访问一些资源
开发人员在开发过程中使用各自本机的数据库,如何配置数据库地址、账号和密码
假设说最后一项,每个开发要使用自己本机的数据库,你可能会说让每个人修改自己的appsettings.config,在提交代码的时候不提交就行了。那么如果在appsettings.config添加其他配置项的时候,显然不提交appsettings.config文件不合理的。

现在,ASP.NET Core 提供了一种很优雅简洁的方式 User Secrets 用来帮助我们解决这个事情。

机密管理器

机密管理器工具存储 ASP.NET Core 项目开发期间的敏感数据。 在此上下文中,一段敏感数据是应用机密。 应用机密存储在与项目树不同的位置。 应用机密与特定项目关联,或者跨多个项目共享。 应用机密不会签入到源代码管理中。

机密管理器工具的工作原理

机密管理器工具会隐藏实现详细信息,例如值的存储位置和存储方法。 可在不知道这些实现详细信息的情况下使用该工具。 这些值存储在本地计算机的用户配置文件文件夹中的 JSON 文件中:

Windows文件系统路径:

%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json

Linux/macOS 文件系统路径:

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

在上述文件路径中,将 <user_secrets_id> 替换为在项目文件中指定的 UserSecretsId 值。

不要编写依赖于使用机密管理器工具保存的数据的位置或格式的代码。 这些实现详细信息可能有变。 例如,机密值不会加密,但将来可能会加密。

启用机密存储

在 Visual Studio 2022 中,在解决方案资源管理器中右键单击该项目,然后从上下文菜单中选择“管理用户机密”。

该操作会将 UserSecretsId 元素添加到项目文件的 PropertyGroup 中。 默认情况下,UserSecretsId 的内部文本是 GUID。 内部文本是任意的,但对于项目来说是唯一的。

<PropertyGroup>
<UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>

在应用程序中使用用户机密

要在应用程序中访问配置的用户机密,你需要保证project.json文件中存在依赖项:

Microsoft.Extensions.Configuration.UserSecrets 并且builder.AddUserSecrets()。

然后在Startup.cs文件中通过 Configuration 对象访问

var builder = WebApplication.CreateBuilder(args);
var movieApiKey = builder.Configuration["ApiKey"];

实际操作

1. 新建工程n01UserSecrets. 将项目添加到解决方案中

dotnet new blazorserver -o n01UserSecrets
dotnet sln add n01UserSecrets/n01UserSecrets.csproj

2. 在解决方案资源管理器中右键单击n01UserSecrets项目,然后从上下文菜单中选择“管理用户机密”。

打开的文件内容替换为

{
"ApiKey": "12345"
}

3. Program.cs 文件使用

var movieApiKey = builder.Configuration["ApiKey"];
Console.WriteLine(movieApiKey);

4. Razor 页面使用

Key is @apiKey

@code{
[Inject] IConfiguration? config { get; set; } string? apiKey { get => config!["ApiKey"]; }
}

5. 不同项目共享机密存储文件

以控制台为例

dotnet new console -o n01UserSecretsConsole
dotnet sln add n01UserSecretsConsole/n01UserSecretsConsole.csproj

5.1. 在解决方案资源管理器中右键单击n01UserSecretsConsole项目,然后从上下文菜单中选择“管理用户机密”。

5.2. 双击项目n01UserSecrets,打开项目配置,找到UserSecretsId一行,整行复制

<UserSecretsId>979b4b67-add4-46bb-80c6-49dab268ca91</UserSecretsId>

5.3. 在解决方案资源管理器中右键单击n01UserSecretsConsole项目,然后从上下文菜单中选择“管理用户机密”。

5.4. 双击项目n01UserSecretsConsole,找到UserSecretsId一行,替换为复制的内容

<UserSecretsId>979b4b67-add4-46bb-80c6-49dab268ca91</UserSecretsId>

5.5. Program.cs 文件测试效果

using Microsoft.Extensions.Configuration;
IConfiguration? Config; Config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
var apiKey = Config["ApiKey"];
Console.WriteLine(apiKey);

.NET CLI

  • 启用机密存储
dotnet user-secrets init
  • 设置机密
dotnet user-secrets set "Movies:ServiceApiKey" "12345"

在上述示例中,冒号表示 Movies 是具有 ServiceApiKey 属性的对象文字。

  • 列出机密
dotnet user-secrets list
  • 删除单个机密
dotnet user-secrets remove "Movies:ConnectionString"
  • 删除所有机密
dotnet user-secrets clear

优先级

注意:如果你的appsetting.json文件中有和secrets.json文件中相同节点(冲突)的配置项,那么就会被secrets.json中的设置项给覆盖掉,因为 builder.AddUserSecrets()晚于 AddJsonFile("appsettings.json")注册, 那么我们可以利用这个特性来在每个开发人员的机器上重新设置数据库连接字符串了。

总结

以上,或许可以感受到微软在 ASP.NET Core 中对于开发人员还是非常贴心的,很多小细节都考虑到了,因此在我们构建应用程序的过程中,可以多使用这些小功能(特性)来让我们的代码更加的优雅~

参考资料

项目源码

Github | Gitee

关联项目

FreeSql QQ群:4336577(已满)、8578575(已满)、52508226(在线)

BA & Blazor QQ群:795206915、675147445

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

AlexChow

今日头条 | 博客园 | 知乎 | Gitee | GitHub

Blazor 在开发环境保存机密(User Secrets)的更多相关文章

  1. ASP.NET Core 优雅的在开发环境保存机密(User Secrets)

    前言 在应用程序开发的过程中,有的时候需要在代码中保存一些机密的信息,比如加密密钥,字符串,或者是用户名密码等.通常的做法是保存到一个配置文件中,在以前我们会把他保存到web.config中,但是在A ...

  2. ubuntu中使用机密数据Secrets

    目录 AptNetCore使用Secrets管理私密数据 前言 使用 设置UserSecretsId 设置机密 代码中访问机密 脚注 AptNetCore使用Secrets管理私密数据 前言 在项目中 ...

  3. Blazor+Dapr+K8s微服务之开发环境调试

    1         安装Dapr开发调试环境 1.1         Dapr 完整安装模式不支持开发调试 在上一篇随笔<Blazor+Dapr+K8s微服务之服务调用>中,我们通过为每个 ...

  4. 构建一个基本的前端自动化开发环境 —— 基于 Gulp 的前端集成解决方案(四)

    通过前面几节的准备工作,对于 npm / node / gulp 应该已经有了基本的认识,本节主要介绍如何构建一个基本的前端自动化开发环境. 下面将逐步构建一个可以自动编译 sass 文件.压缩 ja ...

  5. 在Ubuntu下搭建ASP.NET 5开发环境

    在Ubuntu下搭建ASP.NET 5开发环境 0x00 写在前面的废话 年底这段时间实在太忙了,各种事情都凑在这个时候,没时间去学习自己感兴趣的东西,所以博客也好就没写了.最近工作上有个小功能要做成 ...

  6. 自定义搭建PHP开发环境

    学习了一段时间php了,因为之前是刚接触php,所以用的是集成安装包(wamp).现在想进一步了解apache.mysql.php之间的关系以及提升自己所以进行自定义搭建PHP开发环境.废话不多说,请 ...

  7. 打造TypeScript的Visual Studio Code开发环境

    打造TypeScript的Visual Studio Code开发环境 本文转自:https://zhuanlan.zhihu.com/p/21611724 作者: 2gua TypeScript是由 ...

  8. PHP开发环境的配置

    PHP的开发环境主要包括:安装和配置Apache服务器.PHP引擎以及MySQL数据库服务器,另外选用Dreamweaver作为PHP的开发工具. 1.安装和测试Apache 首先下载Apache:官 ...

  9. 【工匠大道】Mac下Java开发环境配置简述

    本文地址 原文地址 分享提纲: 1. 下载JDK1.7 2. 配置java_home 3 .安装tomcat 4 .安装eclipse或者myeclipse 5.  mysql安装 破解版下载请参考M ...

随机推荐

  1. es6 快速入门 系列 —— 对象

    其他章节请看: es6 快速入门 系列 对象 试图解决的问题 写法繁杂 属性初始值需要重复写 function createPeople(name, age){ // name 和 age 都写了 2 ...

  2. mybatis——逆向工程中 where (条件1)and (条件2 or 条件3 or 条件4)

    where (条件1)and (条件2 or 条件3 or 条件4) = where (条件1 and 条件2)or (条件1 and 条件3) or (条件1 and 条件4) 结果 是这样的 WH ...

  3. Java 代码注意细节

    代码优化的目标是: 1.减小代码的体积 2.提高代码运行的效率 代码优化细节 1.尽量指定类.方法的final修饰符 带有final修饰符的类是不可派生的.在Java核心API中,有许多应用final ...

  4. Flash XSS

    示例: 创建一个测试flash,代码如下,导出swf文件 //取m参数 var m=_root.m; //取showInfo参数 var showInfo=_root.showInfo; //调用ht ...

  5. 一图学Python

    网上有这样一张图片,信息量很大,通常会被配上标题"一张图让你学会Python": 这张图流传甚广,但我没有找到明确的出处,图片上附带了 UliPad 的作者 Limodou 的信息 ...

  6. DLink 815路由器栈溢出漏洞分析与复现

    DLink 815路由器栈溢出漏洞分析与复现 qemu模拟环境搭建 固件下载地址 File DIR-815_FIRMWARE_1.01.ZIP - Firmware for D-link DIR-81 ...

  7. java实现稀疏矩阵的压缩与解压

    任务要求 把棋盘当作一个稀疏矩阵,0表示没棋,1表示黑棋,2表示蓝棋. 把该稀疏矩阵压缩以三元组形式表示并以文件形式保存,再写另一个程序读取文件中的信息把压缩后的三元组还原成原来的稀疏矩阵. 其中三元 ...

  8. Redis常见问题及其场景问题

    假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以 某个固定的已知的前缀开头的,如果将它们全部找出来?   使用 keys 指令可以扫出指定模式的 key 列表. 对方接着追 ...

  9. @Autowired 注解有什么用?

    @Autowired 可以更准确地控制应该在何处以及如何进行自动装配.此注解用于在 setter 方法,构造函数,具有任意名称或多个参数的属性或方法上自动装配bean.默认情况下,它是类型驱动的注入. ...

  10. 哪些是重要的 bean 生命周期方法?你能重载它们吗?

    有两个重要的 bean 生命周期方法,第一个是 setup , 它是在容器加载 bean 的时候被调用.第二个方法是 teardown 它是在容器卸载类的时候被调用. The bean 标签有两个重要 ...