前言
在應用程式開發的過程中,有的時候需要在程式碼中儲存一些機密的資訊,比如微信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 中對於開發人員還是非常貼心的,很多小細節都考慮到了,因此在我們構建應用程式的過程中,可以多使用這些小功能(特性)來讓我們的程式碼更加的優雅~
參考資料
專案原始碼
關聯專案
FreeSql QQ群:4336577(已滿)、8578575(已滿)、52508226(線上)
BA & Blazor QQ群:795206915、675147445
知識共享許可協議
本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名AlexChow(包含連結: https://github.com/densen2014 ),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。如有任何疑問,請與我聯絡 。