所以我有一个基本的数据库,密码只使用基本的crypt()函数进行哈希处理(不是很好的做法,对吧?
我现在正在尝试制作登录页面。这是我的基本代码。
if (isset($_POST['username'])
&& isset($_POST['input_password'])
&& !empty($_POST['username'])
&& !empty($_POST['input_password'])) {
$username = trim($_POST['username']);
$input_password = trim($_POST['input_password']);
$sql = "SELECT username, password FROM registration WHERE username=? && password=?";
我真的很挣扎。我可以用基本文本作为密码进行登录,可以让它工作。但是哈希固有的验证方面正在抛弃我。
我知道我需要做一些类似于:
if(crypt($input_password, $db_pass)==$db_pass) //plus the username stuff
echo 'Logged in!';
}
我是否需要先执行单独的 SELECT 查询才能从输入的用户名中获取密码?然后通过crypt用数据库密码验证输入的密码?
所以喜欢:
$sql = "SELECT username, password FROM registration WHERE username=?";
$stmt = $db -> prepare($sql);
$stmt -> bind_param('s', $username);
$stmt -> execute();
$stmt -> bind_result($db_user, $db_pass);
$stmt -> fetch();
if(crypt($input_password, $db_pass)==$db_pass) //plus the username stuff
echo 'Logged in!';
}else{
echo 'Not logged in';
}
这是正确的方式吗?仅通过用户名直接从数据库中获取密码似乎不是很安全。但我想不出任何其他方法。
注意:这不是为了实际用途,只是为了教育。
您不必检查if
语句中的密码是否相同,SQL 查询就足够了。
查看检索到的行计数是否为>= 1 就足够了。
最佳做法是在数据库中保存密码的哈希版本,然后使用 SELECT 查询查找用户名和哈希密码是否与提供的凭据相同。
我的观点是,在查询中使用它们之前,您应该比使用 isset 和 !empty 更好地限定 POST。
更好的方法是为密码生成哈希,并在 SELECT 查询中使用哈希,然后比较用户名。
原因是这样你就把SQL注入排除在外了。出于同样的原因,我也要求在适用的情况下使用一个数值(例如最后 4 个,电话)用 intval($_POST['number'])
限定它。
我的首选哈希值是$hash = hash('ripemd320',$password);
我不知道它今天是否仍然适用,但在我研究哈希算法时,ripemd320 是从未被破解过的算法。
即便如此,我仍然检查输入值,看看他们是否发布了任何包含通常用于SQL注入的SQL的内容:
$strike1 = preg_match_all('/'x2C/',$inputValue,$matches, PREG_SET_ORDER);
$strike2 = preg_match_all('/['x21-'x2F]|['x3A-'x40]|['x5B-'x60]|['x7B-'x7F]/',$inputValue,$matches, PREG_SET_ORDER);
$strike3 = preg_match_all('/COALESCE|0x|like|regex|mid|select|delete|drop|insert|do|call|replace|update|infile|lock|set|from|into|show|table|kill|reset/i',$inputValue,$matches, PREG_SET_ORDER);
请记住,我已经老了,并且已经这样做了很长时间。所以是的,我的代码可能使用折旧的 PHP。
我还关注蛮力攻击。
这段代码来自我的早期,可以改进。 但它有效。
$sql = "SELECT `ip`,`TimeStamp` FROM `access` WHERE `ip` LIKE '$ip' AND `TimeStamp` > CURRENT_TIMESTAMP order by `TimeStamp` ASC";
$results = @mysql_query($sql);
$rows = mysql_num_rows($results);
if ($rows == 1) {
$ipCount = 1;
$timeCount = abs(strtotime($row[1]) - time());
$timeMin = $time;
$timeMax = $time;
}
$row = @mysql_fetch_array($results, MYSQL_NUM);
if ($rowCount > 1) {
$saveIP[$ipCount++] = $row[0];
$saveTime[$timeCount++] = strtotime($row[1]);
while ($row = mysql_fetch_array($results, MYSQL_NUM)) {
$saveTime[$timeCount] = strtotime($row[1]);
$time = $saveTime[$timeCount] - $saveTime[$timeCount - 1];
if ($time > $timeMax){
$timeMax = $time;
}
if ($time < $timeMin){
$timeMin = $time;
}
$rowCount += $row[0];
if ( !in_array($row[0],$saveIP)) {
$saveIP[$ipCount++] = $row[0];
$saveIP = $row[0];
$ipCount++;
}
}
}
如果我发现不可接受的行为:
@mysql_query("INSERT INTO `_portal`.`Banned` (`ip`, `TimeStamp`,`Strikes`, `Attributes`) VALUES ('$ip', CURRENT_TIMESTAMP, $alert);");
特别是在共享服务器上,明智的做法是不要将mysql_connect()
放在公共脚本中,如果服务器配置错误,而 PHP 作为 MIME 类型文本/纯文本提供,则不要将数据库名称和密码暴露在外。 并不少见。 在共享服务器上,我已经能够使用. Opps,不打算发布该代码。
为了连接,我使用类似include('/home/user/secureStorage/P7gAv2fH4pU.php');
当对脚本的访问是管理性的时,我只允许从我的IP访问。
if ((hash('ripemd320',$passcode) == '6732f3c024fe3c3c1ccd7dbe5d0fa7d4a53c516f800707bb86a9017c1e1646d9d4a2d7adc56a505d') && (substr($ip,0,11) == '152.30.52.72' || $ip == '72.3.150.55' || $ip == '17.162.23.21' )){
$admin = true;
}