10

我想为我的网站创建一个用户管理系统,

什么对安全性和性能更好。

类型 1:

table_user : user_id , user_name , user_email , user_password . user_phone ...

或者

类型 2:

table_user : user_id , user_name , user_email ...
table_pass : user_id , user_password .
table_phone: user_id , user_phone .

哪一个更好 ?

4

4 回答 4

22

理想情况下:

  • 根本不存储密码(即使是加密的)。存储从密码派生的哈希值。
  • 对密码加盐以防止彩虹攻击
  • 将散列放在一个单独的数据库服务器上,在它自己的防火墙和它自己定义良好的 API 1后面。这个 API 应该只做三件事:
    1. 对于给定的用户名,检索相应的密码哈希。
    2. 对于给定的用户名,设置新的哈希(以支持重置密码)。
    3. 删除给定的用户名及其哈希(以支持用户注销)。
  • 对盐做同样的事情:把它们放在自己的服务器上,放在自己的防火墙和 API 后面。这个 API 应该只做三件事:
    1. 对于给定的用户名,检索相应的盐。
    2. 对于给定的用户名,将新盐设置为随机值(以支持重置密码)。
    3. 删除给定的用户名及其盐(以支持用户注销)。
  • 哈希服务器和盐服务器都应该与世界(以及彼此)切断,并且只能从运行您的 Web 应用程序的服务器(即 PHP 或 ASP.NET 或其他...)访问。

当用户尝试通过输入用户名和密码登录时:

  • 确保这是通过 HTTPS 完成的,以便输入的数据安全地到达您的服务器。
  • 调用检索用户名密码哈希的 API。
  • 调用为用户名检索盐的 API。
  • 对用户输入的密码进行加盐和哈希处理,并将其与检索到的哈希值进行比较。
  • 如果它们匹配,则授予用户访问权限。

就其本质而言,哈希是不可逆的——除了用户之外,没有人,甚至你,都不知道确切的密码。如果用户忘记密码,您不能将密码发送给他们,但您可以允许他们重置密码,前提是他们通过了一些额外的验证(即可以访问特定的电子邮件地址和/或回答秘密)问题)。

顺便说一句,登录是一种相对罕见的操作,因此除非您完全忽略正确的索引,否则它不太可能造成性能瓶颈。


1例如,实现一个 Web 服务,然后只打开该 Web 服务所需的端口,不打开其他任何东西。

于 2012-11-10T21:21:51.137 回答
4

我会选择选项 1。

想想有成千上万的用户。因此,要获取用户数据,您将不得不处理 n 个表而不是 1 个表,这显然会在服务器上添加 LOAD,最后您将获得 BAD PERFORMANCE。

所以,我会选择选项1。

对于电话。number,将字段添加为landline_number,mobile_number,alternate_number 作为在表中添加字段不会产生太大的区别,然后为字段添加表。

是的,根据史蒂夫的评论,使用安全散列机制存储密码。

那么你会选择什么选项呢?

于 2012-11-10T14:46:17.437 回答
2

首先,正如@Steve 评论的那样,您应该使用安全的散列机制存储密码——存储纯文本密码是不负责任的——这意味着任何可以侵入你系统的人都知道他们可能在其他网站上重复使用的用户密码。

其次,这两种设计都没有内在的安全性或性能优势 - 从安全性的角度来看,您必须假设可以访问您的数据库的攻击者可以运行查询,并且在这两种设计中检索数据都非常容易计划。从性能的角度来看,如果您有主/外键索引,则选项 2 中的连接成本不太重要。

如果您需要在一段时间后重新设置密码,并且您需要存储密码历史记录以防止人们重复使用密码(例如,这是 Windows 支持的功能),您需要有一个“UserPassword”表,带有 valid_from 和 valid_until 列。

于 2012-11-10T14:38:05.950 回答
1

这取决于。如果您想保留密码历史记录并且如果用户可以拥有许多电话号码,那么您可以为密码和电话创建额外的表格。在其他情况下,一张桌子就足够了。

于 2012-11-10T14:25:27.943 回答