PHP网站用户认证的最佳实践


PHP best practice on user authentication for a website?

我用非常简单的php代码构建了几个网站,到目前为止还不错,但碰巧我现在担心主题"安全",我想知道在php中创建登录/身份验证过程的最佳方法是什么

这是我目前所做的:

在注册时,用户提交一个电子邮件和密码密码将以md5字符串的形式存储在mysql中,这样除了用户之外任何人都可以知道。

当用户登录时,我做

SELECT * FROM usertable WHERE email = $emailsubmitted AND pass = md5($passsubmitted)

则如果结果数组的大小大于0,则表示用户存在

所以我设置

session_start(); 
$_SESSION['logged'] = 'true';
$_SESSION[userid] = userid;

所以对于用户浏览的每个页面,我将执行一个检查,看看是否存在会话变量

总结:我想知道这是否足够安全,以及如何改进。

您的SQL语句中存在注入漏洞。(这是在假设"submitted"后缀意味着变量没有经过任何过滤的情况下进行的。)如果恶意用户将'admin@example.com' AND 1=1;--作为电子邮件地址提交,他们可以使用"admin@example.com"凭据登录,而无需考虑密码。我建议保护SQL的输入和/或使用存储过程。我还建议只加载你绝对需要的列;它将提高查询的速度,并允许更少的状态在数据库之外被挂起。

另外,在密码上实现盐。如果有人要从数据库中检索用户的数据,那么密码将很容易成为暴力破解和字典攻击(如彩虹表)的目标。如果你真的很偏执,考虑从MD5切换到SHA或其他哈希函数。

确保在php.ini文件中设置了哪些变量,并将它们设置为您期望的值。根据这些设置,数组分配给$_SESSION也是不安全的。一些旧的web应用程序利用PHP的"特性",使查询字符串中的变量成为web应用程序中的全局变量,这意味着当它执行$_SESSION['userid'] = $userid;时,如果恶意用户将?userid=1附加到其查询字符串中,他们将成为用户ID为1的用户,这通常是第一个用户(或管理员)。

一般逻辑是好的,是的。但是,对密码进行简单的md5验证并不好。

  • 不加盐会使哈希对彩虹表的查找是开放的。

  • md5通常不被认为是一个好的密码散列机制。我鼓励你看看http://www.openwall.com/phpass/

旁注:您的SQL 似乎对SQL注入是开放的。

在前面提到的SQL注入之上,我建议您不要检查数组是否大于零,而是检查数组是否等于1。

原因是,假设有人修改了你的数据库,只是运行一个简单的查询来清除所有的密码或将它们设置为特定的条目,然后检查是否等于1将阻止这种情况。

同样,假设多个用户有相同的密码,他们以某种方式SQL注入用户名,或者你忘记检查用户名,那么检查等于1也是安全的。

最终,这是一件小事,但当涉及到安全性时,每一点都很重要。

我注意到的第一件事是您将MD5散列应用于php变量。这让我觉得密码在信道上传播得很清楚。

你应该在客户端使用js应用MD5哈希,这里有一个例子:

http://phpjs.org/functions/md5/

如果你想增加另一层安全,你还应该考虑在标准哈希之外使用盐。这将保护您免受任何字典攻击或反向访问(参见此:http://tools.benramsey.com/md5/)