我是 PHP 的新手,这也是我的第一个登录系统,如果你们能看一下我的代码并找出任何安全漏洞那就太好了:
注意:尽管此处未显示,但我正在对所有用户输入进行消毒处理。
注册:
步骤1:我将用户选择的密码传递给以下函数:
encrypt($user_chosen_password, $salt);
function encrypt($plain_text, $salt) {
if(!$salt) {
$salt = uniqid(rand(0, 1000000));
}
return array(
'hash' => $salt.hash('sha512', $salt.$plain_text),
'salt' => $salt
);
}
步骤2:我会将散列值和盐值($password['hash']
和 $password['salt']
)存储在数据库中的用户表中:
id | username | password | salt | unrelated info...
-----------------------------------------------------------
1 | bobby | 809a28377 | 809a28377f | ...
fd131e5934
180dc24e15
bbe5f8be77
371623ce36
4d5b851e46
登录:
步骤1: 我获取用户输入的用户名并在数据库中查找是否有任何行返回。在我的网站上,没有2个用户可以共享相同的用户名,因此用户名字段始终具有唯一的值。如果我返回了1行,我会获取该用户的salt。
步骤2: 然后我运行用户输入的密码通过加密函数(如上面先前发布的)但这次我还提供从数据库检索到的salt:
encrypt($user_entered_password, $salt);
步骤3:现在我有了要与之匹配的正确密码,保存在变量$password['hash']
中。因此,在数据库上进行第二次查找以查看输入的用户名和哈希密码是否同时返回一行。如果是,则用户凭据正确。
步骤4:为了在用户凭据通过后登录用户,我生成一个随机唯一字符串并对其进行哈希处理:
$random_string = uniqid(rand(0, 1000000));
$session_key = hash('sha512', $random_string);
然后我将$session_key
插入到数据库中的active_sessions
表中:
user_id | key
------------------------------------------------------------
1 | 431b5f80879068b304db1880d8b1fa7805c63dde5d3dd05a5b
步骤 5:
我将上一步生成的未加密唯一字符串 ($random_string
) 设置为一个名为 active_session
的 cookie 的值:
setcookie('active_session', $random_string, time()+3600*48, '/');
步骤6:
在我的header.php
文件的顶部,有这个检查:
if(isset($_COOKIE['active_session']) && !isset($_SESSION['userinfo'])) {
get_userinfo();
}
get_userinfo()
函数在数据库的users
表上进行查找,并返回一个关联数组,该数组存储在名为userinfo
的会话中。
// 首先,此函数获取活动会话cookie的值并对其进行哈希以获取会话密钥:
hash('sha512', $random_string);
// 然后它在active_sessions
表上进行查找,以查看是否存在一个由此key
相关的记录,如果是,则将获取与该记录关联的user_id
并使用其进行第二次查找users
表来获取userinfo
:
$_SESSION['userinfo'] = array(
'user_id' => $row->user_id,
'username' => $row->username,
'dob' => $row->dob,
'country' => $row->country,
'city' => $row->city,
'zip' => $row->zip,
'email' => $row->email,
'avatar' => $row->avatar,
'account_status' => $row->account_status,
'timestamp' => $row->timestamp,
);
如果存在userinfo
会话,我知道用户已通过身份验证。如果不存在该会话但存在active_session
cookie,则在header.php
文件顶部的检查将创建该会话。我之所以使用cookie而不仅仅是会话,是为了保持登录状态。因此,如果用户关闭浏览器,则会话可能消失,但cookie仍然存在。由于在
header.php
的顶部有检查,因此会话将被重新创建,用户可以像正常登录用户一样运行。登出:
第1步:取消设置
userinfo
会话和active_session
cookie。第2步:从数据库中删除
active_sessions
表中的相关记录。注意:唯一的问题是,如果用户伪造
active_session
cookie并在其浏览器中自行创建它,则可能存在其他问题(也许还有很多)。当然,他们必须将该cookie的值设置为一个字符串,该字符串在加密后必须与来自active_sessions
表中的记录匹配,我将从该记录中检索user_id
以创建该会话。我不确定实际上,对于用户(可能使用自动程序)来说,猜测一个他们不知道将被sha512加密后与数据库中的字符串匹配以获取用户ID以构建该会话的字符串的准确机会是多少。抱歉写了这么大一篇文章,但由于这是我网站的如此关键部分,并且由于我的经验不足,我只是想请更有经验的开发人员进行审核,以确保它实际上是安全的。
那么,您是否发现了这种方法中的任何安全漏洞,并且该如何改进?
mt_rand()
而不是rand()
。 - Grexis