Безопасность аторизации/регистрации/сессиям в чистом PHP

Это скорее не вопрос как исправить то, что не работает а как защитить то, что работает. Прочитал что хранить user_id в $_SESSION небезопасно, но тогда и непонятно как его узнать после авторизации.

//Авторизация
session_start();

if(!empty($_POST['email']) && $_POST['password'])) {
   $email     = $_POST['email'];
   $password  = $_POST['password'];
}

//Проверяем есть ли такой юзер в базе по логину и паролю и совпадают ли они
$isAccount = $database->has("account", [
        
    "email"    => $email,
    "password" => $password

]);

//Узнаем по email user_id и role
if ($isAccount) {

    $userdata = $database->select("account", [
        "user_id",
        "role",
        "email"
    ], [
        "email" => $email
    ]);

    foreach ($userdata as $user) {

    }

    //Записываем дату и время последнего входа
    $date = date("Y-m-d H:i:s");
    $database -> update("account", [
        "last_login" => $date
    ],[
        "user_id" => $user['user_id']
    ]); 
        
    //И вот здесь возникает вопрос, правильно ли это?
    //Может будут какие рекомендации?
    $_SESSION['user_logged_in'] = [
        "user_id"    => $user['user_id'],
        "role"       => $user['role']
    ];

}

Далее в header на страницах user_id берется так:

session_start();

if (!empty($_SESSION['user_logged_in'])) {
    $user_auth = $_SESSION['user_logged_in'];
    $user_id = $user_auth['user_id'];
}else{
    $user_auth = false;
}

Ответы (1 шт):

Автор решения: ALexander Lead

При создании сессии создается уникальный идентификатор, который отправляется браузеру в виде куки и сохраняется на пользовательском компьютере: https://www.php.net/manual/ru/session.examples.basic.php Такой способ имеет потенциальные угрозы в зависимости от настроек на стороне пользователя, вот некоторые потенциальные примеры: https://habr.com/ru/post/120636/ Поэтому для защиты обычно добавляют различные дополнительные способы, например:

  • сохраняют в сессии IP пользователя;
  • сохраняют данные системы;
  • сохраняют данные браузера;
  • сессию дополняют идентификаторами сеанса, чтобы исключить повторное обращение пользователя; и т.п.

В частности в вашем примере проверка не происходит никакая, только на наличие данных в сессии.

Так же в вашем примере похоже есть ошибка: при сохранении данных сессии вы создаете массив второго уровня

    $_SESSION['user_logged_in'] = [
    "user_id"    => $user['user_id'],
    "role"       => $user['role']
];

а при проверке данных обращаетесь вообще к массиву $user_auth

if (!empty($_SESSION['user_logged_in'])) {
$user_auth = $_SESSION['user_logged_in'];
$user_id = $user_auth['user_id'];

}

Т.е. в вашей сессии достаточно просто получить идентификатор сессии и можно подключаться к серверу

→ Ссылка