【问题标题】:How to keep multiple connectionString passwords safe, separate, and easy to deploy?如何保持多个 connectionString 密码安全、独立且易于部署?
【发布时间】:2011-03-02 10:58:06
【问题描述】:

我知道这里已经有很多关于这个主题的问题(我已经阅读了尽可能多的内容),但我还没有弄清楚如何最好地满足我的特定标准。以下是目标:

  1. ASP.NET 应用程序将在几个不同的 Web 服务器上运行,包括用于开发的 localhost 工作站。 这意味着使用机器密钥加密 web.config 已失效。 Web 服务器的每个“类型”或环境(dev、test、prod)都有自己对应的数据库(dev、test、prod)。我们希望将这些连接字符串分开,以便在“dev”代码上工作的开发人员无法看到任何“prod”连接字符串密码,也不允许这些生产密码被部署到错误的服务器或提交给 SVN。

  2. 应用程序应该能够根据服务器名称(使用 switch 语句)决定尝试使用哪个连接字符串。例如,“localhost”和“dev.example.com”应该知道使用 DevDatabaseConnectionString,“test.example.com”将使用 TestDatabaseConnectionString,“www.example.com”将例如,使用 ProdDatabaseConnectionString。这样做的原因是为了限制发生任何部署事故的机会,即错误类型的 Web 服务器连接到错误的数据库。

  3. 理想情况下,完全相同的可执行文件和 web.config 应该能够在任何这些环境中运行,而无需在每次部署时单独定制或配置每个环境(这似乎很容易在部署期间忘记/搞砸了一天,这就是为什么我们不再只有一个必须在每个目标上更改的连接字符串)。目前通过 FTP 完成部署。 更新:使用“构建事件”并修改我们的部署程序可能不是一个坏主意。

  4. 我们将无法通过命令行访问生产 Web 服务器。这意味着使用 aspnet_regiis.exe 加密 web.config 已失效。 更新:我们可以通过编程方式执行此操作,因此这一点没有实际意义。

  5. 我们希望不必在密码更改时重新编译应用程序,因此使用 web.config(或 db.config 或其他)似乎最有意义。

  6. 开发人员应该无法获取生产数据库密码。如果开发人员将源代码检查到他们的 localhost 笔记本电脑上(这将确定它应该使用 DevDatabaseConnectionString,记得吗?)并且笔记本电脑丢失或被盗,则应该无法获取其他连接字符串。因此,不能考虑使用单个 RSA 私钥来解密所有三个密码。 (与上面的#3相反,如果我们走这条路,我们似乎需要三个单独的密钥文件;这些可以在每台机器上安装一次,如果错误的密钥文件部署到错误的服务器,最糟糕的情况是应该发生的是应用程序无法解密任何内容——并且不允许错误的主机访问错误的数据库!)

  7. 更新/附录:该应用程序有几个独立的面向 Web 的组件:一个经典的 ASMX Web 服务项目、一个 ASPX Web 窗体应用程序和一个较新的 MVC 应用程序。为了不让在每个单独的项目中为每个单独的环境配置相同的连接字符串而发疯,最好只出现在一个地方。 (可能在我们的 DAL 类库或单个链接的配置文件中。)

我知道这可能是一个主观问题(要求以“最佳”方式做某事),但鉴于我提到的标准,我希望确实会出现一个最佳答案。

谢谢!

【问题讨论】:

    标签: asp.net security encryption web-config


    【解决方案1】:
    1. 您可以拥有多个具有相同加密密钥的 Web 服务器。您可以在机器配置中执行此操作,只需确保每个键都相同。

    ..

    一种常见的做法是将第一个加密的连接字符串存储在机器上的某处,例如注册表。在服务器使用该字符串连接后,它将检索将在数据库中管理的所有其他连接字符串(也加密)。这样可以根据授权要求(请求者、正在使用的应用程序等)动态生成连接字符串,例如,可以根据上下文和用户/组以不同的权限访问相同的表

    我相信这个场景解决了你的所有(或大部分?)观点。

    【讨论】:

    • 关于在每个人的机器(服务器和开发工作站)上使 machine.config 相同,这不会允许开发人员解密生产数据库连接字符串吗?我希望实现一种分离,这不可能是可能的。 (最坏的情况是,开发人员的笔记本电脑被盗,可以用来访问它!)
    • no.. 如果你不能在一台机器上破解加密,为什么你能在另一台机器上做同样的事情?在所有 Web 服务器上使用相同的密钥并不会降低安全性。
    • 如果我们为开发人员提供与生产网络服务器上使用的相同的机器密钥,他们(或窃取他们计算机的人)不需要“破坏”任何东西。我们刚刚给了他们钥匙!
    • 在每个 Web 服务器上使用不同的密钥如何解决您刚刚描述的场景?
    • 我已经编辑了我的问题并澄清了#1。重点是提供一些背景细节,以便得出一个好的解决方案,而不是假设这样的解决方案可能与 machine.config 文件有任何关系。 (这也是我为什么要问的原因!)谢谢!
    【解决方案2】:

    集成身份验证/Windows 身份验证是一个不错的选择。没有密码,至少没有需要存储在 web.config 中的密码。事实上,除非管理员明确将其从我手中夺走,否则这是我更喜欢的选项。

    就个人而言,对于因机器而异的任何内容(不仅仅是连接字符串),我使用这种技术从 web.config 中放入了一个外部引用:http://www.devx.com/vb2themax/Tip/18880

    当我把代码扔给生产服务器管理员时,他得到了一个新的 web.config,但没有得到外部文件——他使用了他之前拥有的那个。

    【讨论】:

    • 使用integrated/windows auth 会简化这一点,但这不会将系统/机器管理员(设置用户/凭据/域等)的负担从程序员身上转移出去吗?如果有人想在自己的机器上在家工作,拥有到开发数据库的连接字符串可以让他们直接开始工作,而不必担心这方面的问题。
    • 当我试图弄清楚如何使 ASP.NET 应用程序(类似博客的东西)对于那些不合理的人易于部署时,我对此进行了很多思考要求了解基本的管理任务。我决定只有一个基于文件的数据库就足够简单了。 dasBlog(仅使用 XML 文件作为数据库)就是一个很好的例子。但即便如此,在不再需要配置字符串、密码或用户 ID 之后,您仍然必须使文件可写,并向 IIS 帐户授予 NTFS 写权限。为了最简单,找到一个没有任何安全性的 DB+网络服务器。
    • 使用单独的 .config 文件当然是一个好主意,我正在研究。在每个中使用不同的密钥名称(与特定的服务器名称相关联,正如我们目前已经在做的那样)可以消除在错误环境中使用错误文件的可能性。我们可能不希望将此文件签入 SVN,以尽量减少有人抓取此文件的错误“版本”,当然也不要将密码暴露给它。
    • 在没有任何安全性的情况下运行站点/数据库肯定是最简单的形式;不幸的是,我们需要我们可爱的 SQL Server,并且只允许合适的人在其中查看!
    【解决方案3】:

    (首先,哇,我认为 2 或 3 个“快速段落”比我想象的要长一点!我开始...)

    我已经得出结论(也许你会不同意我的观点),在服务器上(或使用 aspnet_iisreg)“保护”web.config 的能力只有有限的好处,也许也许不是一件好事,因为它可能会给人一种虚假的安全感。我的理论是,如果有人能够首先访问文件系统以读取此 web.config,那么他们也可能有权创建自己的简单 ASPX 文件,该文件可以“取消保护”并揭示其秘密给他们。但是,如果未经授权的人在您的文件系统中四处乱窜——嗯……那么您手头就有更大的问题,所以我现在的全部担忧都没有实际意义! 1

    我还意识到,也没有一种万无一失的方法可以在 DLL 中安全地隐藏密码,因为它们最终可以通过使用 ILDASM 之类的东西被反汇编和发现。 2 可以通过混淆和加密二进制文件(例如使用 Dotfuscator)来获得 security 模糊性的额外衡量标准,但这并不被视为“安全”。再说一次,如果有人对您的二进制文件和文件系统具有读取权限(并且可能也有写入权限),那么您又会遇到更大的问题。

    为了解决我提到的不希望密码存在于开发人员笔记本电脑或 SVN 中的担忧:通过一个不存在于 SVN 中的单独“.config”文件来解决这个问题(现在!)是显而易见的选择。 Web.config 可以在源代码控制中愉快地生活,而只有秘密部分不能。然而——这就是为什么我用这么长的回复来跟进我自己的问题——我仍然采取了一些额外的步骤来尝试让这个问题变得更安全,那么至少稍微模糊

    我们想要保密的连接字符串(开发密码以外的那些)永远不会以纯文本形式存在于任何文件中。这些现在首先使用秘密(对称)密钥进行加密——当然,使用新的可笑 Encryptinator(TM)!专为此目的而构建的实用程序——在它们被放入“db.config”文件的副本之前。然后 db.config 仅上传到其各自的服务器。密钥被直接编译到 DAL 的 dll 中,然后(理想情况下!)它本身会被进一步混淆和加密,比如 Dotfuscator。希望这至少可以避免任何偶然的好奇心。

    我完全不会担心 DLL 或 SVN 或开发人员笔记本电脑上的对称“DbKey”。我要保密的是密码本身。为了开发和调试,我们仍然需要在项目中有一个“db.config”文件,但是除了开发密码之外,其中包含所有假密码。实际的服务器有实际的副本,只有它们自己的正确秘密。 db.config 文件通常会(使用 SVN)恢复到安全状态,并且永远不会与真正的机密一起存储在我们的 subversion 存储库中。

    说了这么多,我知道这不是一个完美的解决方案(是否存在?),并且仍然需要一个带有一些部署提醒的便利贴,但它看起来确实足够一个额外的层除了最聪明和最坚定的攻击者之外,所有的麻烦都可能会被拒之门外。我不得不让自己接受“足够好”的安全措施,这并不完美,但确实让我在给它“大学尝试!”感觉很好之后重新开始工作!


    1. 根据我在 6 月 15 日的评论http://www.dotnetcurry.com/ShowArticle.aspx?ID=185 - 如果我不在基地,请告诉我! -还有一些更好的评论在这里Encrypting connection strings so other devs can't decrypt, but app still has access这里Is encrypting web.config pointless?和这里Encrypting web.config using Protected Configuration pointless?

    2。 在这里就不同主题但非常相关的概念进行很好的讨论和思考:Securely store a password in program code? - 真正重要的是从所选答案链接的 Pidgin 常见问题解答:如果有人有你的程序,他们可以了解它的秘密。

    【讨论】:

      猜你喜欢
      • 2022-11-07
      • 1970-01-01
      • 2013-10-24
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 2011-09-18
      • 2020-03-18
      相关资源
      最近更新 更多