Я новичок в 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 пользователей, которые могут делиться одинаково
username, поэтому поле username всегда имеет уникальное значение. Если мне вернули 1 строку, я взял соль для этого пользователя.
Шаг 2: Затем я запускаю введенный пользователем пароль с помощью функции шифрования (как ранее было опубликовано выше), но на этот раз я также добавляю соль, полученную из базы данных:
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
), и устанавливаю ее в качестве значения файла cookie, который я называю active_session
:
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 active_session и хэширует его, чтобы получить session_key:
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
существует, я знаю, что пользователь аутентифицирован. Если он не существует, но существует файл cookie active_session
, то эта проверка
в верхней части файла header.php
будет создан этот сеанс.
Причина, по которой я использую файлы cookie, а не только сеансы, заключается в сохранении имени входа. Так что, если пользователь закрывает браузер, сеанс может исчезнуть, но
cookie все еще будет существовать. А поскольку эта проверка находится в верхней части header.php
, сеанс будет воссоздан, и пользователь может работать как зарегистрированный пользователь.
у пользователя как обычно.
Выйти:
Шаг 1: Сеанс userinfo
и cookie active_session
не установлены.
Шаг 2: Связанная запись из таблицы active_sessions
в базе данных удалена.
Примечания: Единственная проблема, которую я вижу (и, возможно, есть много других), заключается в том, что пользователь подделывает этот файл cookie active_session
, создавая его самостоятельно в своем браузере. Конечно, они должны установить в качестве значения этого файла cookie строку, которая после его шифрования должна соответствовать записи в таблице active_sessions
, откуда я получу user_id
для создания этого сеанса. Я не уверен, каковы шансы на то, что это реально, для пользователя (возможно, использующего автоматизированную программу), чтобы правильно угадать строку, которую он не знает, будет затем sha512 зашифровано и сопоставлено со строкой в таблице active_sessions
в база данных для получения идентификатора пользователя для создания этого сеанса.
Извините за большое эссе, но так как это очень важная часть моего сайта, и из-за моей неопытности я просто хотел запустить его более опытными разработчиками, чтобы убедиться, что это действительно безопасно.
Итак, вы видите какие-либо дыры в безопасности на этом маршруте и как его можно улучшить?