Я новичок в 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']
) в таблице users в базе данных:
id | username | password | salt | unrelated info...
-----------------------------------------------------------
1 | bobby | 809a28377 | 809a28377f | ...
fd131e5934
180dc24e15
bbe5f8be77
371623ce36
4d5b851e46
Вход:
Шаг 1: Я беру имя пользователя, введенное пользователем, и просматриваю базу данных, чтобы узнать, возвращены ли какие-либо строки. На моем сайте нет 2 пользователей, которые могут делиться одним и тем же имя пользователя, поэтому поле имени пользователя всегда имеет уникальное значение. Если я получу 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
include есть эта проверка:
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
в базе данных удаляется.
Примечания. Единственная проблема, которую я вижу (и, возможно, многие другие), заключается в том, что пользователь подделывает этот active_session
cookie, создавая его самостоятельно в своем браузере. Конечно, они должны установить в качестве значения cookie строку, которая после ее зашифрования должна соответствовать записи в таблице active_sessions
, откуда я буду получать user_id
для создания этого сеанса. Я не уверен, какие шансы на это реалистично, для пользователя (возможно, с использованием автоматизированной программы), чтобы угадать строку, которую они не знают, будет зашифрована sha512 и сопоставлена с строкой в таблице active_sessions
в базу данных, чтобы получить идентификатор пользователя для создания этого сеанса.
Извините за большое эссе, но так как это такая важная часть моего сайта, и из-за моей неопытности я просто хотел запустить ее более опытными разработчиками, чтобы убедиться, что она действительно безопасна.
Итак, вы видите дыры в безопасности на этом маршруте и как его можно улучшить?