我知道这个话题已经有很多问题了(我已尽可能多地阅读),但我还没有弄清楚如何最好地满足我的特定标准。以下是目标:
ASP.NET应用程序将在几个不同的Web服务器上运行,包括用于开发的localhost工作站。 这意味着使用机器密钥加密web.config。 Web服务器(dev,test,prod)的每个“类型”或环境都有自己的相应数据库(dev,test,prod)。我们希望将这些连接字符串分开,以便处理“dev”代码的开发人员无法看到任何“prod”连接字符串密码,也不允许将这些生产密码部署到错误的服务器或提交给SVN。 / p>
应用程序将应该能够根据服务器名称(使用switch语句)决定尝试使用哪个连接字符串。例如,“localhost”和“dev.example.com”将知道使用DevDatabaseConnectionString,“test.example.com”将使用TestDatabaseConnectionString,“www.example.com”将例如,使用ProdDatabaseConnectionString。这样做的原因是为了限制任何部署事故的可能性,其中错误类型的Web服务器连接到错误的数据库。
理想情况下,完全相同的可执行文件和web.config应该能够在任何这些环境中运行,而无需在每次部署时单独定制或配置每个环境(这似乎很容易在部署期间忘记/搞砸了一天,这就是为什么我们不再只有一个必须在每个目标上更改的连接字符串。部署目前通过FTP完成。 更新:使用“构建事件”并修改我们的部署过程可能不是一个坏主意。
我们不会对生产Web服务器进行命令行访问。这意味着使用aspnet_regiis.exe来加密web.config。 更新:我们可以通过编程方式执行此操作,所以这一点没有实际意义。
我们宁愿不必在密码更改时重新编译应用程序,因此使用web.config(或db.config或其他)似乎最有意义。
开发人员不应该访问生产数据库密码。如果开发人员将源代码检查到他们的localhost笔记本电脑上(这将确定它应该使用DevDatabaseConnectionString,记得吗?)并且笔记本电脑丢失或被盗,则不应该获取其他连接字符串。因此,不能考虑使用单个RSA私钥来解密所有三个密码。 (与上面的#3相反,如果我们走这条路线,看起来我们需要有三个单独的密钥文件;这些可以在每台机器上安装一次,如果错误的密钥文件被部署到错误的服务器,最差的应该发生的是应用程序无法解密任何东西---并且不允许错误的主机访问错误的数据库!)
UPDATE / ADDENDUM:该应用程序有几个独立的面向Web的组件:经典的ASMX Web服务项目,ASPX Web窗体应用程序和更新的MVC应用程序。为了不为每个单独的环境在每个单独的项目中配置相同的连接字符串而疯狂,最好只将它出现在一个地方。 (可能在我们的DAL类库或单个链接的配置文件中。)
我知道这可能是一个主观问题(要求采用“最好”的方式做某事),但考虑到我提到的标准,我希望确实会出现一个最好的答案。
谢谢!
答案 0 :(得分:3)
集成身份验证/ Windows身份验证是一个不错的选择。没有密码,至少没有密码需要存储在web.config中。事实上,除非管理员明确地将其从我身边带走,否则这是我更喜欢的选择。
就个人而言,对于任何因机器而异的东西(不仅仅是连接字符串),我使用这种技术从web.config中输入一个外部引用:http://www.devx.com/vb2themax/Tip/18880
当我将代码放到生产服务器管理员的篱笆上时,他获得了一个新的web.config,但没有获得外部文件 - 他使用的是他之前的文件。
答案 1 :(得分:1)
..
一种常见的做法是将第一个连接字符串存储在计算机上的某个位置,例如注册表。在服务器使用该字符串连接之后,它将检索将在数据库中管理的所有其他连接字符串(也是加密的)。这样,连接字符串可以根据授权要求(请求者,正在使用的应用程序等)动态生成,例如,根据上下文和用户/组,可以使用不同的权限访问相同的表
我相信这个场景可以解决所有(或大多数?)你的观点..
答案 2 :(得分:1)
(首先,哇,我认为2或3个“快速段落”比我想象的要长一点!我走了......)
我得出结论(也许你不同意我的意见),在服务器上(或使用aspnet_iisreg)“保护”web.config的能力只有有限的好处,也许也许不是一件好事,因为它可能会给人一种虚假的安全感。我的理论是,如果有人能够获得对文件系统的访问权以便首先读取这个web.config,那么他们也可能有权创建自己的简单ASPX文件,该文件可以“解除保护”并揭示其秘密给他们。但是,如果未经授权的人在您的文件系统中遇到麻烦......那么您手头有更大的问题,所以我现在的整个问题都没有实际意义! 1
我也意识到,在DLL中安全隐藏密码并不是一种万无一失的方法,因为它们最终可以通过使用类似ILDASM的东西进行反汇编和发现。 2 通过对二进制文件进行模糊处理和加密,例如使用Dotfuscator,可以获得安全性模糊性的额外度量,但这不能被视为“安全”。再说一次,如果有人对您的二进制文件和文件系统具有读访问权限(并且可能也可以写访问权限),那么您再次遇到了更大的问题。
为了解决我提到的关于不希望密码存在于开发者笔记本电脑或SVN上的问题:通过单独的“.config”文件来解决这个问题,这个文件并不存在于SVN中(现在!)是一个非常明显的选择。 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常见问题解答:如果有人有你的程序,他们可以了解它的秘密。