问题 请批评我的PHP身份验证工作


发布后 这个 不久前,我决定用PHP创建自己的注册/认证功能。我希望任何人都能指出改进的缺陷/机会,尤其是会议中存储的内容......

逻辑流程是:

1 - 用户注册使用电子邮件作为用户名,“网站名称”然后构成他们将访问的任何网址的一部分,密码至少6个字符,必须包含字母和数字(我知道这可能更强)

2 - 如果用户和站点是唯一的,我然后将这两者以及随机生成的字符串(salt)存储在我的数据库的auth表中。然后,我获取用户密码,将salt连接到它,并将此salted密码的md5哈希存储在同一数据库行中

3 - 当用户登录时,我获取她输入的密码并将盐连接到它,创建一个md5哈希值,并将其与我在数据库中存储的内容进行比较 - 如果它们匹配,则用户已输入正确的密码,其用户名将写入会话

4 - 在每个请求中,我使用会话中存储的用户名来查询数据库并读取与此用户关联的站点名称。然后我将它与url本身的站点名称进行比较,如果它们匹配,我设置一个可供其余或脚本访问的变量(不是全局变量,它只能由我的控制器读取,它决定用户是否可以看到特定页面)如果两个站点名称不匹配,则将用户重定向回登录

我担心的是有人可以写入会话,因此如果他们知道他们注册的用户名,就可以访问人们页面吗?你会如何防止这种情况发生?

在任何人指责我疏忽之前,这是一个个人学习项目的方式 - 我不会暴露任何客户数据!


7873
2018-03-03 18:27


起源

您应尽可能重用现有的身份验证框架,因为实际上它很复杂。例如,看看 github.com/delight-im/PHP-Auth 这与框架无关,与数据库无关。 - caw


答案:


  1. 为什么6个字符?使其更大,并且至少需要6个(或更多)字符。将密码中的字符数限制为6没有任何借口。

  2. 在会话中放置超过用户名。但要安全地执行此操作,您必须在每次登录时更改盐:

A-从登录页面:使用现有盐进行名称和密码验证。如果有效,用新盐更新用户表盐和密码(您拥有用户的密码,这样您就可以再次使用它和盐)。将密码的md5写入会话。 B-从任何其他页面:将用户和散列密码与数据库进行比较。如果它们不匹配,请重定向到登录页面。

这个想法的缺陷是用户无法在多台机器/浏览器上维护登录。

您的注册系统需要工作。你怎么知道这个电子邮件地址有效?您如何知道用户注册拥有电子邮件地址?您必须向包含返回您网站的链接的地址发送电子邮件,在您允许帐户访问任何内容之前必须单击该链接。否则,有人可以在其他人的电子邮件地址下注册,向该人提出欺诈性声明,或者只是让您的网站向该网站发送垃圾邮件,让您的网站关闭。

您还可能希望调查CAPTCHA以限制脚本注册。


8
2018-03-03 18:46



感谢Joe - Re 6 charachters,它已经是至少6而不是6,我将编辑澄清。重新写密码到会话,是每次写一些不同的想法,这样被盗的会话数据只有在重新登录之前才有效? - Rob Y
是。否则,有人可以永久重用会话(或者直到用户更改密码。有人会说每个页面的值都会改变,但是你需要在会​​话中存储原始密码。这对我来说没什么意义。 - jmucchiello


简短回答:看起来不错!

答案很长:

  1. 是的,您应该允许更强/更长的密码,否则这是可以的。只需确保您只接受有效的网址部分字符(我会坚持使用PCRE字符)作为网站名称。但是,“验证此电子邮件”系统是合适的,以确保注册人实际控制提供的电子邮件地址。
  2. 看起来不错。不过,我比shad更喜欢sha1。
  3. 只要您的会话是安全的,您可以存储的不仅仅是用户名(对于每个页面请求,这将是一个相当昂贵的SQL查找 - 继续存储他们的PK)。
  4. 看起来不错,但应根据我在#3中的评论进行调整

要确保正确处理会话安全性,请检查 PHPSec指南


3
2018-03-03 18:51





  • 限制登录时的速度。记录用户的每次尝试,并在经过多次失败尝试后将其锁定。当失败的尝试安装时,锁定越来越长。

  • 在代码中添加一个静态的salt,并将其与数据库中的salt结合使用。然后,如果你的数据库被黑客入侵,他们仍然没有代码中的salt。这种盐不能/不应该改变。

  • 用户可以检索密码/重置锁定吗?你需要收集挑战问题和答案。

  • 当用户重置密码时,他们是否必须知道原始密码?

如果这是一个安全的网站,或只是一个跟踪某人的网站。我知道您可以从机器到机器登录的网站。它总是记得你,但只是一个论坛,所以麻烦的可能性很低。

为什么要加密代码以及数据库? 一旦您的数据库遭到黑客入侵,您的网站就会被祝酒。然而,看到用户倾向于在许多网站上使用相同的密码,没有任何意义帮助破解每个人的财产。如果他们也得到你的代码,那么王室​​的拧紧就会发生,但是我们尽可能多地设置障碍。

通过默默无闻的安全是愚蠢的,但许多安全层可以提供帮助。

关于在会话中输入用户名 哈希用户名,网址和盐。将其存储在数据库和会话中。使用它作为身份验证,如果无效则将它们转储到登录。他们不能将cookie复制到另一个站点,他们不会公开他们的用户名,并且它会消除查询。

您甚至可以在每个X页面视图中重新生成该盐值并将其存储在会话中以使其过期,并且随着时间的推移窃取它不那么有用。然后,您将在数据库中存储两个盐。一个用于密码,一个用于验证会话值。


3
2018-03-03 19:00



我不得不说,虽然你在你的第二个子弹中所说的是真的,但是一旦数据库被黑了,那么游戏有点起来,不是吗? = P - Peter Bailey
Retrive密码 - 新的密码通过电子邮件发送到用户地址,并在下次登录时被迫更改用户需要知道现有的p / w才能更改 - Rob Y
更新了我对盐渍代码的想法 - MrChrister
这个答案中也有一些好东西。 - jmucchiello


如果有人正在观看提交的注册表格,那么他们就会得到您所关注的信息。第一步:对表单使用HTTPS。

至于加密的数据库内容,我会让别人对此提出异议。 :-)


1
2018-03-03 18:30





我担心的是有人可以写入会话,因此如果他们知道他们注册的用户名,就可以访问人们页面吗?你会如何防止这种情况发生?

我不确定你是什么意思。怎么会有人“写入会议”?会话[通常]是存储在服务器上的文件,客户端无法查看或修改该文件。

如果您担心会话劫持(也就是固定),那么您需要在URL字符串中启用SSL并禁用会话ID。 (见php.ini的 session.use_only_cookies

4 - 在每个请求中,我使用会话中存储的用户名来查询数据库并读取与此用户关联的站点名称。然后我将它与url本身的站点名称进行比较,如果它们匹配,我设置一个可供其余或脚本访问的变量(不是全局变量,它只能由我的控制器读取,它决定用户是否可以看到特定页面)如果两个站点名称不匹配,则将用户重定向回登录

这听起来像是最大的担忧。网站名称是什么样的?你是如何将它与URL匹配的?正则表达式?

关于这方面的一些更多细节会很好,因为如果您的访问控制有缺陷,那么您的身份验证质量并不重要。


1
2018-03-07 15:44





如果我得到正确的流量,那么如果我知道你的用户名和网站名称,请转到网站名称并给你一个带有用户名的cookie(因为会话,毕竟保存为cookie),我在 - 没有密码需要?这不是一个缺陷吗?


0
2018-03-04 20:51



我看过这个,据我所知,会话ID存储为cookie,但没有变量吗? - Rob Y
你的第四点说“在每次请求时,我都使用存储在会话中的用户名”(可伪造),然后将其与网址本身的网站名称进行比较。所以,如果我把它们都伪造 - 我就在。 - Liorsion