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

时间:2009-06-03 22:34:21

标签: php mysql security passwords

我正在使用Mysql,我认为最好将用户个人信息及其登录名和密码分成两个不同的表,然后在两者之间引用它们。

注意:为了澄清我的帖子,我了解保护密码(哈希,盐等)的技巧。我只知道,如果我遵循生命中其他部分(投资,数据备份,甚至是个人存储)的做法,在最坏的情况下(包括表格或火灾),在表格之间分配信息可以保护您的其他数据。

8 个答案:

答案 0 :(得分:38)

不要存储密码。如果它曾经坐在磁盘上,它可能会被盗。而是存储密码哈希值。 Use the right hashing algorithm,如bcrypt(包括盐)。

编辑:OP回复说他理解上述问题。

无需将密码存储在与登录名不同的表中。如果一个数据库表遭到破坏,那么访问同一数据库中的另一个表并不是一个很大的飞跃。

如果您对安全性和深度安全性充分关注,可以考虑将用户凭据存储在与域数据完全独立的数据存储中。通常,一种方法是将凭证存储在LDAP目录服务器中。这可能也有助于您稍后进行的任何单点登录工作。

答案 1 :(得分:18)

密码应存储为加密哈希,这是一种不可逆的操作,可防止读取纯文本。在对用户进行身份验证时,密码输入将经过相同的散列处理并与哈希进行比较。

避免使用快速廉价的哈希,如MD5或SHA1;目标是使攻击者计算彩虹表(基于哈希冲突)的代价高昂;快速哈希抵消了这一点。使用昂贵的哈希对于身份验证方案来说不是问题,因为它对单个哈希运行没有影响。

除了散列之外,用随机生成的值对散列进行加盐;一个随机数,然后存储在数据库中,并在散列之前与数据连接。这增加了计算冲突时必须生成的可能组合的数量,从而增加了生成彩虹表的总体时间复杂度。

您的密码哈希列可以是固定长度;您的加密哈希值应输出可编码为固定长度的值,对于所有哈希值都是相同的。

尽可能避免滚动自己的密码认证机制;使用现有解决方案,例如bcrypt

可以在http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes找到关于如何处理密码以及您需要关注的内容的出色解释。

最后请注意,如果攻击者获得了对您数据库的访问权限,那么您的直接关注应该是他们可能访问的任何敏感或个人识别信息,以及他们可能造成的任何损害。< / p>

答案 2 :(得分:14)

把它们放在同一张桌子里没什么不对。事实上,它会快得多,所以我强烈推荐它。我不知道你为什么要分开它。

答案 3 :(得分:7)

我会尝试回答你原来的问题。将它全部放在一个表中是好的,除非您只是收集了大量的个人信息。在这种情况下,拆分可能是有意义的。该决定应基于您正在处理的个人信息量以及需要访问的频率。

我会说大多数时候我会在一张桌子上做这样的事情:

UserID, FirstName, LastName, Email, Password, TempPassword

但是......如果你收集的远不止于此。假设您正在收集电话,传真,出生日期,传记等等。如果很少访问大部分信息,那么我可能会将其放在自己的表中,并将其与一对一的关系联系起来。毕竟,表上的列越少,对该表的查询就越快。有时,简化访问最多的表是有意义的。虽然每当您需要访问该个人信息时,JOIN的性能都会受到影响,因此您需要考虑这一点。

编辑 - 你知道吗,我只是想到了什么。如果您在用户名或电子邮件字段(根据您的喜好)创建索引,它几乎完全消除了在用户表中创建如此多列的性能缺陷。我这样说是因为每当你登录WHERE子句时,如果它有一个索引,实际上会非常快速地找到用户名,如果你在该表中有100列则无关紧要。 所以我改变了我的看法。我把它全部放在一张桌子里。 ;)

在任何一种情况下,由于安全性似乎是一个热门话题,密码应该是一个哈希值。我建议使用SHA1(或SHA256,如果你真的很关心它)。 TempPassword也应该使用哈希,它只用于忘记密码功能。显然,使用哈希,您无法解密并向用户发送其原始密码。因此,您生成一个他们可以登录的临时密码,然后强制他们在登录后再次更改密码。

答案 4 :(得分:3)

首先,说明(希望)明显,如果你可以以任何方式避免存储用户名和密码这样做;这是一项重大责任,如果您的凭据存储被破坏,它可能会为同一用户提供访问许多其他地方(由于密码共享)。

如果您必须存储凭据:

  • 不要存储可逆形式;使用SHA-256等公认算法存储哈希值。使用来自信誉良好的可信赖来源的加密软件 - 不要试图自己动手,否则你可能会错。
  • 对于每个凭据集,将盐与散列数据一起存储;这用于“填充”散列,使得两个相同的密码不会产生相同的散列 - 因为这会泄露密码是相同的。
  • 使用安全的随机生成器。弱随机性是加密相关安全性失败的首要原因,而不是密码算法。

如果您必须存储可逆凭据:

  • 选择一个好的加密算法 - AES-256,3DES(过时)或公钥密码。使用来自信誉良好的可信赖来源的加密软件 - 不要试图自己动手,否则你可能会错。
  • 对于每个凭证集,存储salt(未加密)以及加密数据;这用于“填充”加密密码,使得两个相同的密码不会产生相同的密码文本 - 因为这会泄露密码是相同的。
  • 使用安全的随机生成器。弱随机性是加密相关安全性失败的首要原因,而不是密码算法。
  • 将加密/解密密钥与数据库分开存储在O / S安全文件中,只能由应用程序运行时配置文件访问。这样,如果您的数据库被破坏(例如通过SQL注入),您的密钥不会自动受到攻击,因为这通常需要访问HDD。如果您的操作系统支持与配置文件绑定的文件加密,请使用它 - 它只能提供帮助,而且通常是透明的(例如NTFS加密)。
  • 如果可行,请使用主密码存储密钥本身。这通常意味着您的应用。将需要在启动时键入的密码 - 在脚本的参数中提供它是没有用的,因为如果您的硬盘被破坏,您必须假设密钥文件和脚本都可以被查看。
  • 如果不需要用户名来查找帐户记录,则加密用户名和密码。

答案 5 :(得分:2)

根据我的个人经验,在这种情况下,将个人信息和登录信息存储在各个数据库中是最佳做法。原因是应该进行SQL注入,它是有限的(除非渗透者知道数据库的内部布局)到数据所属的表,而不是提供对整个数据集的访问。 / p>

但是,请注意,这可能需要执行更多查询,从而降低性能。

答案 6 :(得分:2)

所有这些数据是否始终与用户保持1:1的关系?如果您可以预见允许用户拥有多个地址,电话号码等,那么您可能希望将个人信息分成单独的表格。

答案 7 :(得分:0)

您应该将它们存储在同一个表中,并使用单向加密。 MD5可以工作,但很弱,所以你可能会考虑像SHA1或其他方法。将2个项目存储在单独的表格中没有任何好处。