2010-08-20 131 views
5

我有一个登录服务到我目前的网站,我想知道的是 - 是否有任何特定的方法,你可以称之为最安全?PHP/MySQL安全登录和会话

让我解释一下我的系统好一点:

我现在有一个用户表中的PHP MySQL数据库。用户名和密码都存储为VARCHAR(不是我所知道的最好的密码)。

在注册表单方面,我通过仅允许a-Z 0-9条目并限制字符数来规定密码和用户名的选择。在登录表单一侧,我通过使用mysql_real_escape_string来停止攻击,并使用POST来代替AJAX的iFrame。

我觉得我正在尽我所能来防止来自Form侧的攻击,但不能从数据库端进行攻击。我知道你可以在进入数据库时​​改变密码存储的类型来进行加密,但是我不明白的是如何查询这个加密的字符串。

鉴于我所描述的,你会建议如何增加安全性,为什么?你选择什么方法来防止黑客攻击?你能看到我所描述的任何明显的安全漏洞吗?也许最重要的是,考虑到我从未参与过网络游戏开发并且没有太多经验,我该怎么做才能纠正这些问题?

(记住,我不会创建一个系统,以容纳机密或炎症数据)

+1

最安全的方式是SSL +个人证书。虽然我怀疑你的网站确实需要最安全的网站。 – 2010-08-20 08:59:33

+2

另一件要提及的事情。一个聪明的SOer说,安全不是可以被添加的东西。这不是一件事,它是一个过程。 – 2010-08-20 09:02:40

+0

但是,即使是任何过程都可以细分为一系列操作说明。这将是系统完成时的一个过程。 – 2010-08-20 09:11:14

回答

5

首先,不要明文密码存储在数据库中。因此,注册新用户时,请将其密码输入为hash。 MD5最常用于此。我建议用这个盐。因此,对于存储:

$password = md5($yoursalt . $_POST['password']); 

现在,当用户想要登录,您再次在您的文章有自己的密码。现在制作和以前一样的散列,然后在数据库中搜索这个散列(用他们的用户名)。这样你就不会存储他们的实际密码。

+2

+1决定使用哪一个用于“至少使用散列和盐”,-1用于“使用MD5" 。现在是2010年,密码哈希的MD5是死的。请至少使用一种SHA-2功能。 – Piskvor 2010-08-20 09:43:52

+0

谢谢,这已经是一个很大的帮助。我的思考过程在用户输入密码并从数据库获得加密密码后停止,因此我没有真正想到加密输入的密码并进行比较。谢谢 – 2010-08-20 09:46:01

+0

另外,'$ yoursalt'应该是每个用户,而不是每个站点;这在你的回答中没有明确提及。 – Piskvor 2010-08-20 10:07:25

3

将密码散列到MD5或SHA1是网络安全的重要组成部分。然后匹配密码的方法是首先使用提供的用户名从数据库中检索哈希密码,对用户提供的密码进行哈希处理,然后匹配两个哈希值。由于MD5和SHA1是单向哈希值,这意味着如果用户丢失了密码,则无法检索当前密码。新密码需要重新创建。你可以通过使用PHP mcrypt()函数来解决这个问题。

您还应该允许在密码中使用特殊字符。这只会增加暴力攻击的复杂性。

您也可以在3次错误尝试后锁定一段时间的帐户,甚至在10次尝试后锁定IP地址。尽管后者属于“焦油坑”类别。只是让黑客更加困难一点。

+0

谢谢。我正试图使用​​一些加密,正如我在上面的答案中所说的,我的想法并没有延伸到加密输入的密码和比较:(谢谢你的答案非常清楚,许多人只会抛出很多的行话我的方式,并没有经验(我只有22)它不会是最好的学习方法 – 2010-08-20 09:50:08

+0

密码是密码是非常危险的,因为它是可逆的..没有密码保护方法应该是可逆的 – MRW 2010-08-23 14:02:32

1

生成密码时,我总是用一个用户特定的盐,所以我的“用户”表有两个字段“encrypted_salt”和“密码”

顶部和它的底部是我SHA1(encrypted_salt +“密码“);

当生成encrypted_salt时,我会使用sha1(unqid(true));它可以产生几乎100%的独特的盐,因为它使用时间以毫秒为单位,并有额外的熵(盐)。获得重复的可能性几乎为0。

所以:

$salt = sha1(unqid(true)); 
$password = sha1($_POST['password']); 

在数据库存储中:

$pw = sha1($salt.$password); or sha1($password.$salt); 

它并不真正的问题。

SHA1的美妙之处在于它总能生成40个字符的字符串。你可以越吃越好,特别是如果你可以为每个密码生成一个独特的盐。

+0

我认为基础加密版本的用户名+加密版本,你是否也会认为这是可行的? – 2010-08-20 10:14:33

+0

是的,因为用户的id(pc)应该始终是唯一的,作为一种最佳实践,我总是使用某种时间戳在哈希中,所以您可以使用microtime(true)或time()或unqid()作为2个用户在完全相同毫秒内添加的可能性,尤其是因为PHP不处理多线程。但是username.id会很好,尤其是散列。 – MRW 2010-08-20 10:18:07

+0

使用散列法,我认为sha1 vs md5是个人偏好。我总是使用sha1(),但md5也一样好! – MRW 2010-08-20 10:19:06

1

就你的SQL而言,不要使用类似mysql_real_escape_string的字符串转换函数,它仍然可以允许在某些情况下发生注入攻击。使用参数化查询,从而确保数据库在所有情况下将所有用户提供的字符串视为数据,而不是SQL代码片段。

PHP中的MySQLi和PDO库都支持参数化查询。

+0

谢谢,我将如何将这些库实现到我的代码中?我将如何执行参数化查询? – 2010-08-20 12:00:22

+0

这里有大量的文档和教程。这里有一个http://forum.codecall.net/php-tutorials/12442-php-5-mysqli-prepared-statements.html – Cheekysoft 2010-08-23 09:32:44