我想为我的网站创建一个用户管理系统,
什么对安全性和性能更好。
类型 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 .
哪个更好?
最佳答案
理想情况下:
- 根本不要存储密码(即使是加密的)。存储从密码派生的哈希值。
- Salt防止rainbow attacks的密码.
- 将散列放在单独的数据库服务器上,在其自己的防火墙和自己定义明确的 API 之后1。这个 API 应该只做三件事:
- 对于给定的用户名,检索相应的密码哈希。
- 对于给定的用户名,设置新的哈希值(以支持重置密码)。
- 删除给定的用户名及其哈希值(以支持用户注销)。
- 对盐做同样的事情:将它们放在他们自己的服务器上,并放在他们自己的防火墙和 API 后面。这个 API 应该只做三件事:
- 对于给定的用户名,检索相应的盐。
- 对于给定的用户名,将新盐设置为随机值(以支持重置密码)。
- 删除给定的用户名及其加盐(以支持用户注销)。
- 散列服务器和盐服务器都应该与世界(以及彼此)隔绝,并且只能从运行您的 Web 应用程序(即 PHP 或 ASP.NET 或其他...)的服务器访问。
当用户尝试通过输入用户名和密码登录时:
- 确保这是通过 HTTPS 完成的,以便输入的数据安全地到达您的服务器。
- 调用 API 检索用户名的密码哈希。
- 调用 API 检索用户名的盐。
- 对用户输入的密码进行加盐和哈希运算,并将其与检索到的哈希值进行比较。
- 如果它们匹配,则用户被授予访问权限。
从本质上讲,哈希值是不可逆的——除了用户,没有人知道确切的密码,即使是您也不异常(exception)。如果用户忘记密码,您无法将密码发送给他们,但您可以允许他们重置密码,假设他们通过了一些额外的验证(即可以访问特定的电子邮件地址和/或回答 secret 问题)。
顺便说一句,登录是一个相对很少见的操作,所以它不太可能造成性能瓶颈,除非您完全忽视适当的索引。
1实现 Web 服务,然后仅打开该 Web 服务所需的端口,不打开其他任何端口。
关于mysql - 存储用户并传入单个表或单独的表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13322841/