网页设计欣赏网站,英迈寰球网站建设,怎么建设一个网站赚钱,百度做网站的在Asp.NET Core中如何优雅的管理用户机密数据背景回顾在软件开发过程中#xff0c;使用配置文件来管理某些对应用程序运行中需要使用的参数是常见的作法。在早期VB/VB.NET时代#xff0c;经常使用.ini文件来进行配置管理#xff1b;而在.NET FX开发中#xff0c;我们则倾向… 在Asp.NET Core中如何优雅的管理用户机密数据背景回顾在软件开发过程中使用配置文件来管理某些对应用程序运行中需要使用的参数是常见的作法。在早期VB/VB.NET时代经常使用.ini文件来进行配置管理而在.NET FX开发中我们则倾向于使用web.config文件通过配置appsetting的配置节来处理而在.NET Core开发中我们有了新的基于json格式的appsetting.json文件。无论采用哪种方式其实配置管理从来都是一件看起来简单但影响非常深远的基础性工作。尤其是配置的安全性贯穿应用程序的始终如果没能做好安全性问题极有可能会给系统带来不可控的风向。源代码比配置文件安全么有人以为把配置存放在源代码中可能比存放在明文的配置文件中似乎更安全其实是“皇帝的新装”。在前不久笔者的一位朋友就跟我说了一段故事他说一位同事在离职后直接将曾经写过的一段代码上传到github的公共仓库而这段代码中包含了某些涉及到原企业的机密数据还好被github的安全机制提前发现而及时终止了该行为否则后果不堪设想。于是笔者顺手查了一下由于有意或无意泄露企业机密造成企业损失的案例发现还真不少。例如大疆前员工通过 Github 泄露公司源代码被罚 20 万、获刑半年[1] 这起案件也是一个典型的案例。该员工离职后将包含关键配置信息的源代码上传到github的公共仓库被黑客利用使得大量用户私人数据被黑客获取该前员工最终被刑拘。大疆前员工通过Github泄露公司源代码被罚20万、获刑半年图片来源 http://www.digitalmunition.com/WhyIWalkedFrom3k.pdf[2]大部分IT公司都会在入职前进行背景调查而一旦有案底可能就已经与许多IT公司无缘即便是成为创业者也可能面临无法跟很多正规企业合作的问题。小结所以安全性问题不容小觑哪怕时间再忙也不要急匆匆的就将数据库连接字符串或其他包含敏感信息的内容轻易的记录在源代码或配置文件中。在这个点上一旦出现问题往往都是非常严重的问题。如何实现在.NET FX时代我们可以使用对web.config文件的关键配置节进行加密的方式来保护我们的敏感信息在.NET Core中自然也有这些东西接下来我将简述在开发环境和生产环境下不同的配置加密手段希望能够给读者带来启迪。开发环境在开发环境下我们可以使用visual studio 工具提供的用户机密管理器只需0行代码即可轻松完成关键配置节的处理。机密管理器概述根据微软官方文档[3] 的描述ASP.NET Core 机密管理器[4]工具提供了开发过程中在源代码外部保存机密的另一种方法 。若要使用机密管理器工具请在项目文件中安装包 Microsoft.Extensions.Configuration.SecretManager 。如果该依赖项存在并且已还原则可以使用 dotnet user-secrets 命令来通过命令行设置机密的值。这些机密将存储在用户配置文件目录中的 JSON 文件中详细信息随操作系统而异与源代码无关。机密管理器工具设置的机密是由使用机密的项目的 UserSecretsId 属性组织的。因此必须确保在项目文件中设置 UserSecretsId 属性如下面的代码片段所示。默认值是 Visual Studio 分配的 GUID但实际字符串并不重要只要它在计算机中是唯一的。PropertyGroupUserSecretsIdUniqueIdentifyingString/UserSecretsId
/PropertyGroup
Secret Manager工具允许开发人员在开发ASP.NET Core应用程序期间存储和检索敏感数据。敏感数据存储在与应用程序源代码不同的位置。由于Secret Manager将秘密与源代码分开存储因此敏感数据不会提交到源代码存储库。但机密管理器不会对存储的敏感数据进行加密因此不应将其视为可信存储。敏感数据作为键值对存储在JSON文件中。最好不要在开发和测试环境中使用生产机密。查看引文[5]。存放位置在windows平台下机密数据的存放位置为%APPDATA%\Microsoft\UserSecrets\\secrets.json
而在Linux/MacOs平台下机密数据的存放位置为 ~/.microsoft/usersecrets/user_secrets_id/secrets.json
在前面的文件路径中 user_secrets_id将替换UserSecretsId为.csproj文件中指定的值。在Windows环境下使用机密管理器在windows下如果使用Visual Studio2019作为主力开发环境只需在项目右键单击选择菜单【管理用户机密】即可添加用户机密数据。在管理用户机密数据中添加的配置信息和传统的配置信息没有任何区别。{ ConnectionStrings: { Default: Serverxxx;Databasexxx;User IDxxx;Passwordxxx; } }我们同样也可以使用IConfiguration的方式、IOptions的方式进行配置的访问。在非Windows/非Visual Studio环境下使用机密管理器完成安装dotnet-cli后在控制台输入dotnet user-secrets init
前面的命令将在UserSecretsId .csproj 文件的PropertyGroup中添加.csproj一个元素。 UserSecretsId是对项目是唯一的Guid值。 PropertyGroup TargetFrameworknetcoreapp3.1/TargetFrameworkUserSecretsId79a3edd0-2092-40a2-a04d-dcb46d5ca9ed/UserSecretsId /PropertyGroup
设置机密 dotnet user-secrets set Movies:ServiceApiKey 12345
列出机密 dotnet user-secrets list
删除机密 dotnet user-secrets remove Movies:ConnectionString
清除所有机密 dotnet user-secrets clear
生产环境机密管理器为开发者在开发环境下提供了一种保留机密数据的方法但在开发环境下是不建议使用的如果想在生产环境下对机密数据进行保存该怎么办按照微软官方文档的说法推荐使用Azure Key Vault [6] 来保护机密数据但。。我不是贵云的用户当然买不起贵云不是贵云太贵而是我个人的问题[手动狗头]。其次与Azure Key Valut类似的套件例如其他云差不多都有所以都可以为我们所用。但。。如果您如果跟我一样不想通过第三方依赖的形式来解决这个问题那不如就用最简单的办法例如AES加密。使用AES加密配置节该方法与平时使用AES对字符串进行加密和解密的方法并无区别此处从略。使用数据保护ApiDataProtect Api实现在平时开发过程中能够动手撸AES加密是一种非常好的习惯而微软官方提供的数据保护API则将这个过程进一步简化只需调Api即可完成相应的数据加密操作。关于数据保护api Savorboard[7] 大佬曾经写过3篇博客讨论这个技术问题大家可以参考下面的文章来获取信息。ASP.NET Core 数据保护Data Protection 集群场景【上】[8]ASP.NET Core 数据保护Data Protection 集群场景【中】[9]ASP.NET Core 数据保护Data Protection 集群场景【下】[10](接下来我要贴代码了如果没兴趣请出门左拐代码不能完整运行查看代码来源[11]首先注入配置项 public static IServiceCollection AddProtectedConfiguration(this IServiceCollection services, string directory){services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(directory)).UseCustomCryptographicAlgorithms(new ManagedAuthenticatedEncryptorConfiguration{EncryptionAlgorithmType typeof(Aes),EncryptionAlgorithmKeySize 256,ValidationAlgorithmType typeof(HMACSHA256)});;return services;}
其次实现对配置节的加/解密。使用AES算法的数据保护机制public class ProtectedConfigurationSection : IConfigurationSection{private readonly IDataProtectionProvider _dataProtectionProvider;private readonly IConfigurationSection _p;private readonly LazyIDataProtector _protector;public ProtectedConfigurationSection(IDataProtectionProvider dataProtectionProvider,IConfigurationSection p){_dataProtectionProvider dataProtectionProvider;_p p;_protector new LazyIDataProtector(() dataProtectionProvider.CreateProtector(p.Path));}public IConfigurationSection GetSection(string key){return new ProtectedConfigurationSection(_dataProtectionProvider, _p.GetSection(key));}public IEnumerableIConfigurationSection GetChildren(){return _p.GetChildren().Select(x new ProtectedConfigurationSection(_dataProtectionProvider, x));}public IChangeToken GetReloadToken(){return _p.GetReloadToken();}public string this[string key]{get GetProtectedValue(_p[key]);set _p[key] _protector.Value.Protect(value);}public string Key _p.Key;public string Path _p.Path;public string Value{get GetProtectedValue(_p.Value);set _p.Value _protector.Value.Protect(value);}private string GetProtectedValue(string value){if (value null)return null;return _protector.Value.Unprotect(value);}}
再次在使用前先将待加密的字符串转换成BASE64纯文本然后再使用数据保护API对数据进行处理得到处理后的字符串。private readonly IDataProtectionProvider _dataProtectorTokenProvider;
public TokenAuthController( IDataProtectionProvider dataProtectorTokenProvider)
{
}
[Route(encrypt), HttpGet, HttpPost]
public string Encrypt(string p, string value)
{var protector _dataProtectorTokenProvider.CreateProtector(p);return protector.Protect(value);
}
再替换配置文件中的对应内容。{ConnectionStrings: {Default: 此处是加密后的字符串}
}
然后我们就可以按照平时获取IOptions的方式来获取了。问题公众号【DotNET骚操作】号主【周杰】同学提出以下观点1、在生产环境下使用AES加密其实依然是一种不够安全的行为充其量也就能忽悠下产品经理毕竟几条简单的语句就能把机密数据dump出来。也许在这种情况下我们应该优先考虑accessKeyId/accessSecret尽量通过设置多级子账号通过授权Api的机制来管理机密数据而不是直接暴露类似于数据库连接字符串这样的关键配置信息。另外应该定期更换数据库的密码尽量将类似的问题可能造成的风险降到最低。数据保护api也提供的类似的机制使得开发者能够轻松的管理机密数据的时效性问题。2、配置文件放到CI/CD中发布的时候在CI/CD中进行组装然后运维只是负责管理CI/CD的账户信息而最高机密数据则由其他人负责配置。嗯我完全同意他的第二种做法另外考虑到由于运维同样有可能会有意无意泄露机密数据所以如果再给运维配备一本《刑法》并让他日常补习【侵犯商业秘密罪】相关条款这个流程就更加闭环了。结语本文简述了在.NET Core中如何在开发环境下使用用户机密管理器、在生产环境下使用AESIDataProvider的方式来保护我们的用户敏感数据。由于时间仓促如有考虑不周之处还请各位大佬批评指正。References[1] 大疆前员工通过 Github 泄露公司源代码被罚 20 万、获刑半年: https://www.infoq.cn/article/RZzfel1m6-h8pSK8TTC9[2]http://www.digitalmunition.com/WhyIWalkedFrom3k.pdf: http://www.digitalmunition.com/WhyIWalkedFrom3k.pdf[3] 微软官方文档: https://docs.microsoft.com/zh-cn/dotnet/architecture/microservices/secure-net-microservices-web-applications/developer-app-secrets-storage[4] 机密管理器: https://docs.microsoft.com/zh-cn/aspnet/core/security/app-secrets#secret-manager[5] 查看引文: https://nvisium.com/blog/2019/05/02/Dev-Secrets-and-the-ASP-NET-Core-Secret-Manager.html[6] Azure Key Vault : https://docs.microsoft.com/zh-cn/dotnet/architecture/microservices/secure-net-microservices-web-applications/azure-key-vault-protects-secrets[7] Savorboard: https://home.cnblogs.com/u/savorboard/[8] ASP.NET Core 数据保护Data Protection 集群场景【上】: https://www.cnblogs.com/savorboard/p/dotnetcore-data-protection.html[9] ASP.NET Core 数据保护Data Protection 集群场景【中】: https://www.cnblogs.com/savorboard/p/dotnet-core-data-protection.html[10] ASP.NET Core 数据保护Data Protection 集群场景【下】: https://www.cnblogs.com/savorboard/p/dotnetcore-data-protected-farm.html[11] 查看代码: https://stackoverflow.com/questions/36062670/encrypted-configuration-in-asp-net-core本文首发于溪源的个人博客https://www.techq.xyz/2020/06/09/%E6%8A%80%E6%9C%AF/how-to-manage-user-secret-in-develop-and-production/