乍一看,这可能听起来是一个糟糕的主意,但这是我的场景:我有一个 Windows 服务,它使用用户名身份验证公开多个 WCF 端点。 自定义身份验证器将在本地数据库中查找用户的凭据(密码存储为加盐 SHA-1),或者向另一个服务发出 WCF 请求以验证密码。 (用户对象上有一个枚举,可以是内部的或外部的,指示使用哪个身份验证源)。
我发现对我的服务的每个请求执行查找+哈希检查或进行 WCF 调用的成本很高,因此我想缓存用户名/密码信息。 缓存中的每个项目都有一个生命周期,因此,例如,如果缓存中的项目已存在 60 秒,则在下一个请求时,身份验证器将根据原始源(而不是缓存)验证凭据,然后更新它。
对于本地数据库,我可以简单地将用户名/SHA1 对存储在字典中,并且对于“内部”用户的每个请求,我只需重新散列提供的密码并进行比较。 对于“外部”用户,我只会将明文密码提交给身份验证器,因此由我对其进行哈希处理并将其存储为缓存的一部分。 虽然这确实节省了我数据库请求或远程服务调用的开销,但我仍然必须每次都执行哈希操作。
相关服务将在具有良好物理和网络安全性的内部服务器上运行。 将明文密码存储在缓存中而不是存储哈希版本是否是可接受的做法? 在这种情况下,我的风险似乎是攻击者转储进程的内存并获取密码。 如果我认为这种风险可以接受,是否还有其他原因我应该避免在内存中保存明文密码?
如果我选择使用明文密码,我认为 SecureString 可以在一定程度上限制我的风险。 是否值得麻烦地使用 SecureString(实现起来似乎很迂回)? 我很清楚持久存储未散列的密码的风险,但是我不确定对明文密码的易失性存储的共识是什么。
SecureString 使用加密内存,因此与每次自己进行哈希处理相比,这可能会提高性能。但您必须在您的环境中对其进行分析。
至于在内存中存储明文密码的风险,这不是一个可以在本文中回答的问题。 我只能说,是的,没关系。因为是针对我的情况,出于各种原因。但那不会和你的一样。
我的建议是: 考虑一下密码泄露的后果——对于黑客来说,拥有密码基本上值多少钱($ 或 $$$?)?如今,大多数安全问题都来自经济动机。相对而言,纯粹的破坏行为被这些家伙超越了。
现在将其与以完全不同的方式危害安全性的可能性进行比较,即 SQL 注入或致电用户“验证其帐户”。 如果几个密码的价值很高并且没有其他方法来获取它们,那么也许您应该继续加密它们(现在您已经证明了更强大的服务器的成本是合理的!)。 然后确保您保护加密密钥 - 一旦黑客拥有您的服务器,这些密钥可能就像程序内存一样容易访问。
另一方面,如果该值较低并且存在其他可能的漏洞(而且经常存在),您可以提出合理的论点,即不值得黑客花时间危害服务器并转储内存。
祝你好运。
相关服务将在具有良好物理和网络安全性的内部服务器上运行。
只要从现在到永远(或下一个补丁,以先到者为准),将缓存密码以纯文本形式存储在 ram 中就可以了。如果您将整个密码数据库存储在 ram 中(假设您的持久存储太慢),我认为将它们存储为安全字符串会更好,但由于您最多只存储几个密码 1 分钟,所以我认为没有问题。