НИКОГДА НЕ ИСПОЛЬЗУЙТЕ ЭТОТ КОД!
У вас открыта очень серьезная инъекция SQL. Каждый пользовательский ввод, который вы берете, из файлов cookie или CGI, или везде, где , , должен быть обработан , прежде чем он будет использован в операторе SQL. Я мог бы легко проникнуть в эту систему, попытавшись войти с именем пользователя, например:
user'; UPDATE contractors SET password = '1337'
... после чего я могу войти как любой. Извините, если я звучу агрессивно, но то, что делает этот код, это как забыть запереть входную дверь в вашей компании, которая, вероятно, даже не имеет системы сигнализации.
Обратите внимание, что не имеет значения, действительно ли ввод поступает от пользователя или нет (возможно, он предварительно заполнен, скрыт от). С точки зрения безопасности, все, что поступает из-за пределов , имеет , которое, как считается, содержит злонамеренный ввод пользователя.
Насколько я знаю, вам нужно использовать функцию PDO quote
для правильной очистки строки. (В mysql это будет сделано с mysql_real_escape_string()
.) Я не эксперт по PDO, заметьте, кто-нибудь, пожалуйста, исправьте, если я ошибаюсь.
Кроме того, вам, вероятно, не следует хранить какие-либо пароли непосредственно в базе данных, а использовать хеш-функцию для создания маскированного пароля, а также создавать хеш из предоставленного пользователем пароля и сопоставлять хеш-коды. Для этого вы можете использовать функцию PHP hash
.
Что касается других вопросов, я не знаю, является ли подход, который вы используете в SQL SELECT, лучшим подходом. Я бы просто выбрал соответствующий пароль пользователя и попытался сопоставить его с программой. Я не думаю, что есть какой-то сбой в методе, который вы используете, но он просто не выглядит таким логичным, и, таким образом, есть большая вероятность, что me пропустит какую-то ошибку - что в случае паролей и логины создадут окно для эксплойтов.
Чтобы сделать это по-своему, вы должны заметить, что результат, который вы получаете от PDO query
, равен PDOStatement
, что похоже, нет надежной функции для прямого подсчета количества строк результата. Вам нужно использовать fetchAll
, который возвращает массив строк и считает это. Однако, как я уже сказал, мне все кажется, что он открыт для сбоев, поэтому я чувствовал бы себя безопаснее, проверяя пароль в коде. На мой вкус, слишком большое расстояние от фактического сопоставления паролей, на мой вкус.
Таким образом, чтобы получить полученный пароль для идентификатора пользователя, вы можете использовать PDOStatement fetch()
, который возвращает содержимое столбца из результата. Используйте, например, PDO::FETCH_ASSOC
, чтобы получить их в ассоциативном массиве на основе имен столбцов.
Вот как это исправить:
$userid_dirty = $_POST['userid'];
$password_dirty = $_POST['pass'];
$success = false; // This is to make it more clear what the result is at the end
if ($userid != "" || $password != "") {
$userid = $dbh->quote($userid_dirty);
$passwordhash = hash('sha256',$password_dirty);
$sql = "SELECT userid, passwordhash, company, security_id FROM contractors WHERE userid = ".$userid;
$result = $dbh->query( $sql );
if ($result) { // Check if result not empty, that userid exists
$result_array = $result->fetch(PDO::FETCH_ASSOC);
if ($result_array['PASSWORDHASH'] == $passwordhash) {
// login success
$success = true;
// do all the login stuff here...
// such as saving $result_array['USERID'], $result_array['COMPANY'], $result_array['SECURITY_ID'] etc.
} // else fail, wrong password
} // else fail, no such user
} else {
// fail, userid or password missing
echo ' please enter user id and password.';
}
if (!$success) {
echo ' login failed.';
}
Конечно, код можно немного почистить, но это должно объяснить, что нужно сделать. Обратите внимание, что поскольку пароль хешируется и никогда не используется в SQL , он фактически не нуждается в очистке. Но я оставил его там на всякий случай, поскольку в исходном коде было использовано в запросе.
Обратите внимание, что весь код, касающийся хранения паролей, необходимо изменить, чтобы хранить хэш вместо пароля. Кроме того, было бы очень полезно использовать соль , добавленную к паролю перед хэшированием.
Кроме того, я предоставил код просто для образовательных целей - я просто подумал, что код - это самый простой способ объяснить, как это сделать. Так что не путайте этот сайт с сервисом запроса кода. :)