提问



我正在开发一个必须具有身份验证(用户名和密码)的项目


它还连接到数据库,所以我想我会在那里存储用户名和密码。但是,将密码仅仅放在数据库中的表中的文本字段似乎不是一个好主意。


我正在使用C#并连接到2008 Express服务器。任何人都可以建议(尽可能多的例子)存储此类数据的最佳方法是什么?


P.S我愿意这样的想法,如果可以提供一个很好的理由,这些信息不会存储在数据库中

最佳参考


你是正确的,将密码存储在纯文本字段中是一个可怕的想法。但是,就位置而言,对于您将要遇到的大多数情况(我真的不能想到任何反例)存储表示数据库中的密码是正确的做法。通过表示我的意思是你想要使用salt(对每个用户应该是不同的)和安全的单向算法来存储密码,并存储 ,丢弃原始密码。然后,当您要验证密码时,您将对该值进行散列(使用相同的散列算法和salt)并将其与数据库中的散列值进行比较。


所以,虽然你正在思考这个问题并且这是一个好问题,但这实际上是这些问题的重复(至少):



  • 如何最好地存储用户信息和用户登录名和密码

  • 存储数据库密码的最佳做法

  • 保存密码:最佳实践?

  • 是否可以在php变量或php常量中以明文形式存储密码?



为了进一步澄清盐渍位,简单地对密码进行哈希处理并存储的危险是,如果侵入者获得了数据库,他们仍然可以使用所谓的彩虹表来解密密码(至少显示在彩虹表中的那些)。为了解决这个问题,开发人员为密码添加了一个盐,如果做得好,使得彩虹攻击变得不可行。请注意,一个常见的误解是只需在所有密码中添加相同的唯一和长字符串;虽然这不是可怕的,但最好为每个密码添加唯一的盐。阅读本文了解更多。 [5] [6]

其它参考1


背景
你永远......真的......需要知道用户的密码。你只想验证传入的用户是否知道帐户的密码。


Hash It:
通过强哈希函数存储用户密码哈希(单向加密)。
搜索c#encrypt passwords可以提供大量示例。


请参阅在线SHA1哈希创建器以了解哈希函数产生的内容(但不要使用SHA1作为哈希函数,使用更强大的东西,如SHA256)。[8]


现在,散列密码意味着您(和数据库小偷)不应该将该散列反转回原始密码。


如何使用
但是,你说,我如何使用存储在数据库中的这个混合密码?


当用户登录时,他们会输入用户名和密码(原始文本中)
您只需使用相同的哈希码来哈希该输入密码即可获取存储的版本。


因此,比较两个散列密码(用户名的数据库哈希和键入的密码和哈希密码)。您可以通过比较它们的哈希值来判断他们键入的内容是否与原始用户为其密码输入的内容相匹配。


额外信用:


问题:如果我有你的数据库,那我就不能像开膛手约翰这样的破解者开始哈希,直到找到你存储的哈希密码匹配?
(因为用户选择简短的字典单词......应该很容易)


答案:是的......是的,他们可以。


所以,你应该加盐你的密码。
请参阅有关盐的维基百科文章[9]


请参阅如何使用salt散列数据C#示例[10]

其它参考2


作为密钥加强的盐渍哈希,使用sha-512等安全算法。

其它参考3


最好的安全做法是根本不存储密码(甚至不加密),而是存储加密密码的盐渍哈希(每个密码具有唯一的盐)。


这样(实际上)检索明文密码是不可能的。

其它参考4


我完全建议阅读足够的彩虹表:你需要了解的安全密码方案[[死链接,在互联网档案馆复制]]以及如何安全存储密码。[11] [12]]] [13]


包括我自己在内的许多程序员认为他们理解安全性和散列。可悲的是,我们大多数人都没有。

其它参考5


我可能会略微偏离主题,因为你提到了用户名和密码的需要,而我对这个问题的理解并不是最好的,但OpenID是值得考虑的吗?


如果您使用OpenID,那么如果我正确理解该技术并且用户可以使用他们已有的凭据,那么您根本不会最终存储任何凭据,从而无需创建特定于您的应用程序的新身份。


如果相关的应用程序纯粹是供内部使用,则可能不合适


RPX提供了一种将OpenID支持集成到应用程序中的简便方法。[14]

其它参考6


在您的场景中,您可以查看asp.net成员资格,最好将用户的密码作为散列字符串存储在数据库中。您可以通过将散列的传入密码与存储在数据库中的密码进行比较来验证用户身份。 。


一切都是为此目的而建的,请查看asp.net会员资格[15]

其它参考7


如果您不需要能够反转哈希值,我会将MD5/SHA1作为密码。当用户登录时,您只需加密给定的密码并将其与哈希值进行比较。在这种情况下,哈希冲突几乎是不可能的,除非有人获得对数据库的访问权并查看他们已经发生冲突的哈希。