Аутентификация в PHP. Как организовать её с помощью HTTP-заголовков и cookie?

аутентификация в php. как организовать её с помощью http-заголовков и cookie?

HTTP-аутентификация

В PHP есть базовый инструмент аутентификации пользователя, позволяющий закрывать доступ к различным страницам ресурса. Принцип его использования довольно прост. Браузеру отправляются два специальных заголовка. Один из них устанавливает статус HTTP-ответа в значение 401 (пользователь не авторизован), а другой запрашивает логин и пароль пользователя.

Браузер, получив такой ответ от сервера, самостоятельно откроет диалоговое окно с просьбой ввести необходимые данные. После заполнения полей и нажатия кнопки «Войти» браузер передаст эти данные на сервер. Скрипт, отправивший заголовки, будет запущен снова, но с одним отличием. В суперглобальный массив $_SERVER добавятся два дополнительных элемента: PHP_AUTH_USER и PHP_AUTH_PW. Соответственно в первый передается логин, а во второй — пароль.

//Функция проверки данных, присланных браузером.
function checkUser($login, $password) {
    static $usersIdentity = ['Admin' => 'Tskh@ao78@', 'User' => 'sak7!993$'];

    if (key_exists($login, $usersIdentity)) {
        return ($usersIdentity[$login] === $password);
    }

    return false;
}


//Функция возврата заголовков http-аутентификации
function accessDenied() {
    header('WWW-Authenticate: Basic realm="Secured Zone"');
    header('HTTP/1.0 401 Unauthorized');

    echo '<h1>Доступ запрещен!</h1>';
    echo '<p>Текс будет показан, если пользователь нажмет "отмена"</p>';
}


//Проверяем наличие и корректность присланных данных
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
    if (checkUser($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
        echo "<p>Добро пожаловать {$_SERVER['PHP_AUTH_USER']}</p>";
        exit;
    }
}

accessDenied();

Обратите внимание на пример PHP-скрипта, приведенный выше. Аутентификация пользователя будет считаться неуспешной в случае повторного возврата 401 статуса. Обработка логина и пароля использует специальную функцию. Проверяемые значения строго определены прямо в ней, но вы можете осуществлять проверку с помощью запросов к базе данных.

Если пользователь перезагрузит страницу и скрипт запустится заново, суперглобальный массив $_SERVER по-прежнему будет содержать элементы PHP_AUTH_USER и PHP_AUTH_PW со значениями, присланными ранее. Веб-сервер реализует такое поведение по умолчанию. Сброс этих данных произойдет только в случае закрытия пользователем браузера.

Важно
Такая форма HTTP-аутентификации пользователя не безопасна. Браузер отправляет логин и пароль на сервер в незашифрованном виде. Злоумышленник, прослушивающий сетевой трафик, может с легкостью извлечь их и использовать для своих нужд. Данную проблему в большей степени решает использование защищенного соединения с сервером с помощью SSL-протокола.

Аутентификация через cookie

HTTP-аутентификация имеет ряд существенных недостатков и один из самых важных — это невозможность «разлогиневания» пользователя до закрытия им браузера. Однако в PHP есть ряд инструментов, позволяющих реализовать более гибкий контроль. Для этого служат сессии и cookie. Сессиям будет посвящен отдельный цикл уроков данного учебного курса, поэтому сейчас рассмотрим работу с cookie.

В целом механизм аутентификации можно описать следующим образом:

  1. В случае отсутствия специальной переменной в cookie, показываем пользователю форму ввода логина и пароля.
  2. Осуществляем обработку данных, полученных из формы. Если они корректные, записываем идентификационную переменную в cookie.
  3. Проверяем наличие этого идентификатора при последующих запросах. В случае отсутствия повторяем первый и второй шаг.
  4. Для разлогиневания пользователя в нужный момент удаляем cookie.
//Функция создания защитного кода аутентификации.
function createToken() {
    //Если браузер или ip-адрес не определен, ничего не возвращаем
    if (empty($_SERVER['HTTP_USER_AGENT']) || empty($_SERVER['REMOTE_ADDR'])) {
        return null;
    }

    return sha1($_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR']);
}


//Проверка защитного кода, пришедшего с запросом.
function checkToken() {
    if (isset($_COOKIE['secure']) && ($_COOKIE['secure'] === createToken())) {
        return true;
    }

    return false;
}


//Функция проверки данных из формы аутентификации.
function checkUser($login, $password) {
    static $usersIdentity = ['Admin' => 'Tskh@ao78@', 'User' => 'sak7!993$'];

    if (key_exists($login, $usersIdentity)) {
        return ($usersIdentity[$login] === $password);
    }

    return false;
}


if (checkToken() === true) {
    //Если защитный код установлен и корректен показываем приветствие
    echo "<h1>Добро пожаловать!</h1>";
    echo "Ваш защитный токен: {$_COOKIE['secure']}";

} else {
    //Если из формы присланы данные пользователя, проверяем их.
    //В случае успеха записываем защитный токен в cookie, иначе
    //снова показываем форму.
    if (isset($_POST['login']) && isset($_POST['password'])) {
        if (checkUser($_POST['login'], $_POST['password'])) {
            setcookie('secure', createToken());
            header('Location: /index.php');
            exit;
        }
    }

    echo "
        <form method='post' action='index.php'>
            <h3>Необходимо ввести данные пользователя</h3>
            <input type='text' name='login' placeholder='логин'>
            <input type='password' name='password' placeholder='пароль'>
            <input type='submit' value='Отправить'>
        </form>
    ";
}

Заметка
Обратите внимание. Значение, записываемое в cookie, формируется из ip-адреса пользователя и строки идентифицирующей его браузер. При последующих запросах мы не доверяем полученным данным, а генерируем это значение заново и сравниваем с полученным от браузера.

Таким образом, осуществляется защита от злоумышленника, который мог перехватить этот идентификатор. Так как его ip-адрес будет отличаться от реального пользователя, проверочные коды не совпадут.

Последние публикации