Как сделать сервер авторизации

Добавил пользователь Владимир З.
Обновлено: 04.10.2024

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

Из данной статьи вы узнаете, как установить авторизацию при помощи пароля на веб-сервер Apache, работающий на Ubuntu 16.04.

Требования

Перед тем, как приступить к выполнению дальнейших шагов, убедитесь, что у вас есть доступ к серверу Ubuntu 16.04.

Также для выполнения инструкции вам понадобится следующее:

  • пользователь, который может выполнять команды sudo на вашем сервере;
  • веб-сервер Apache;
  • сайт, на котором установлен SSL-сертификат (к примеру, Let’s Encrypt).

Если все вышеперечисленное у вас в наличии, тогда авторизуйтесь на сервере как пользователь с sudo-правами и перейдите к выполнению первого шага.

Шаг 1: устанавливаем пакет с утилитами Apache

Вам понадобится утилита под названием htpasswd, которая является частью пакета apache2-utils. Она используется для создания файла, а также имени пользователя и паролей, которые будут использоваться для доступа к запрещенному для просмотра обычными пользователями контенту.

Введите следующие команды:

Шаг 2: создаем файл с паролями

Теперь вы можете воспользоваться командой htpasswd. При помощи нее вам будет необходимо создать файл с паролями, который Apache будет использовать для аутентификации пользователей. Для этих целей вам следует создать скрытый файл под названием .htpasswd внутри директории с настройками /etc/apache2.

При первом использовании данной утилиты вам будет необходимо прибавить к команде ключ –c для того, чтобы создать указанный файл. Также в конце команды вам необходимо указать имя пользователя (sinatra в данном примере) – это нужно для того, чтобы создать новую запись внутри файла:

У вас будет запрошен пароль и его подтверждение для созданного пользователя.

Если вы хотите добавить еще каких-либо других пользователей (к примеру, another_user), используйте эту же команду, но уже без ключа –c:

Посмотрите содержимое этого файла:

Вы увидите имя пользователя и зашифрованный пароль для каждой записи:

Шаг 3: настраиваем авторизацию при помощи пароля на Apache

Теперь у вас есть файл с именами пользователей и паролями в формате, доступном для чтения Apache.

Следующим шагом вам необходимо настроить Apache так, чтобы он сверялся с этим файлом всегда, когда собирается предоставить доступ к защищенному от посторонних глаз контенту. Вы можете сделать это двумя путями: либо прямо в файле виртуального хоста сайта, либо добавив файлы .htaccess в директории, доступ к которым вы хотите ограничить.

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

То есть выбирайте путь, исходя из своих требований.

Путь 1 (предпочтительный): настраиваем авторизацию через виртуальный хост

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

Для начала откройте файл виртуального хоста, к которому вы собираетесь ограничить доступ. Для примера в данном руководстве будет использоваться файл 000-default.conf, который содержит в себе виртуальный хост по умолчанию, установленный при помощи пакета Apache в Ubuntu.

Внутри файл с раскомментированными строками будет выглядеть примерно так:

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

Внутри блока директории укажите, что вы хотите установить базовую аутентификацию (Basic). Для графы AuthName необходимо выбрать имя, которое будет отображаться пользователю при запросе данных для аутентификации. В графе AuthUserFile необходимо указать файл с паролем, который был создан ранее, для того, чтобы Apache мог его найти. Также вам понадобится valid-user, который может получить доступ к данным; иными словами, в директорию будет допущен любой, кто сможет подтвердить свою личность при помощи пароля.

После редактирования сохраните и закройте файл.

Перед перезагрузкой сервера проверьте настройки следующей командой:

Если все нормально, и вы увидели Syntax OK, тогда перезагрузите сервер для того, чтобы новая политика доступа с запросом пароля вступила в силу. Для этого введите следующие команды:

Теперь директория, которую вы обозначили ранее, находится под защитой пароля.

Путь 2: настраиваем авторизацию при помощи файлов .htaccess

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

Для того, чтобы при помощи .htaccess файлов активизировать защиту посредством паролей, откройте главный конфигурационный файл Apache:

Далее найдите блок для директории /var/www, который содержит корневой каталог документов. Включите поддержку файлов .htaccess, изменив значение директивы AllowOverride с "None" на "All" – в этом случае сервер будет допускать все директивы .htaccess файла:

После этого сохраните и закройте файл.

Теперь вам необходимо добавить файл .htaccess в директорию, доступ к которой вы хотите ограничить. В данном руководстве для примера доступ будет запрещен ко всему корневому каталогу документов (то есть полностью к сайту), который находится в /var/www/html, но вы можете поместить этот файл в любую директорию, доступ к которой вы хотите ограничить:

Внутри этого файла укажите, что вы хотите установить базовую аутентификацию (Basic). Для графы AuthName необходимо выбрать имя, которое будет отображаться пользователю при запросе данных для аутентификации. В графе AuthUserFile необходимо указать файл с паролем, который был создан ранее, для того, чтобы Apache мог его найти. Также вам понадобится valid-user, который может получить доступ к данным; иными словами, в директорию будет допущен любой, кто сможет подтвердить свою личность при помощи пароля:

Сохраните и закройте файл. Перезагрузите сервер для того, чтобы все изменения, касающиеся защиты паролем выбранной директории, вступили в силу. Затем используйте команду systemctl status для того, чтобы убедиться в успешной перезагрузке:

Шаг 4: проверяем наличие защиты при аутентификации

Для того, чтобы убедиться, что ваши данные защищены, попробуйте получить к них доступ в браузере. Вам должно высветиться окно с запросом имени пользователя и пароля, которое будет выглядеть примерно так:

Как настроить авторизацию по паролю на Apache с Ubuntu 16.04

Если вы введете правильные данные, то вы сможете увидеть запрашиваемые данные. Если вы введете некорректные данные или нажмете отмену (Cancel), то вы увидите страницу с ошибкой (Unauthorized), которая говорит о том, что для не прошедших аутентификацию пользователей доступ запрещен:

Unauthorized
Заключение

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

loader

В прошлом уроке мы изучили механизм взаимодействия с cookie в языке PHP.

Теперь давайте попробуем применить эти знания на практике — создадим простейшую систему авторизации с использованием этих самых cookie. Ведь для авторизации нам просто необходимо при каждом запросе идентифицировать пользователя - сохранив специальное значение в куки этого легко добиться!

Техническое задание

Начнём мы это дело с описания будущей системы. Пусть у нас будут следующие компоненты:

Решение

Продумываем архитектуру

Первое, о чём нам нужно подумать — это то, как будут храниться элементы этой системы, и сколько их вообще будет.

Начнем с простого — для начала у нас должно получиться 3 странички, которые мы описали в ТЗ.

Ещё нам потребуется функционал, который будет проверять, авторизован ли пользователь. Если мы перечитаем ТЗ, то поймём, что он используется в двух местах — и на главной странице и на странице авторизации. Значит, стоит вынести этот механизм в отдельный файл, и использовать его в двух местах сразу.

Пишем код

Все исходники по данному заданию доступны здесь.

База данных

Ну вот, всё продумали, осталось только написать. Предлагаю начать с нашей базы данных. Создадим файл usersDB.php и запишем в него несколько пользователей.

Функции проверки авторизации

Давайте теперь напишем функцию, которая будет проверять, являются ли переданные в неё логин и пароль правильными. Для этого создадим ещё один файл auth.php. В нём нам для получения списка пользователей потребуется подключить файл с базой данных.

В цикле мы пробегаемся по базе данных пользователей и пытаемся найти пользователя с переданными логином и паролем. Если такой пользователь в массиве найден — возвращаем true. Иначе — false.

Давайте теперь ещё напишем функцию, которая будет возвращать логин текущего пользователя. Эта функция будет проверять текущие значения cookie с ключами login и password с помощью уже существующей функции checkAuth. При этом если пользователь найдётся, то она вернёт его login, а иначе — null. Назовём эту нашу новую функцию getUserLogin.

На этом всю логику проверки логина мы описали. Теперь займёмся непосредственно страничками.

Главная страница

Создадим файл index.php. Для простоты примера мы будем использовать только строку с приветствием авторизованного пользователя, либо ссылкой на авторизацию. В этой странице нам потребуется функция проверки авторизации через cookie, поэтому здесь нужно подключить файл auth.php.

Наша главная страничка готова. Можно зайти на неё и убедиться, что мы не авторизованы.

Главная страничка с призывом авторизации

Форма авторизации

Давайте теперь сделаем форму авторизации — создаём файл login.php и для начала набрасываем саму HTML-форму. Шаблон получился следующим.

Давайте теперь добавим логику проверки переданных данных.

Логика простейшая — если был отправлен POST-запрос, проверяем правильные ли логин и пароль были переданы.

Если нет — то создаём переменную $error, в которой пишем об ошибке авторизации. Позже в шаблоне выводим эту ошибку, если эта переменная объявлена.

Если же авторизация прошла успешно, мы устанавливаем cookie с ключами login и password, в которые помещаем значения из POST-запроса. После этого выполняем редирект на главную страницу.

Для формирования заголовков в PHP используется функция header – ознакомиться с ней более детально вы можете здесь.

Теперь можно попробовать нашу страничку в действии. Давайте для начала введём несуществующую пару логина и пароля. Например, 123:123.

Ошибка при авторизации

Мы увидим соответствующую ошибку.

Теперь давайте зайдем под пользователем user. В нашей БД для него указан пароль 123. Пробуем.

Успешная авторизация

Успех! Нас автоматически перекинуло на главную страницу, где мы видим приветствие для данного пользователя!

Безопасная система авторизации

Однако, данная схема имеет недостаток - пароль используется в открытом виде, а это небезопасно. Всё что идёт дальше - только для ознакомления, пока это слишком сложно реализовать без хорошей архитектуры и полноценной базы данных.

Хеширование паролей

В более совершенных системах авторизации используют хеш от пароля.

Если по-простому, то это такое вычисленное значение, полученное в результате выполнения над паролем определенных манипуляций. В результате этих действий мы получаем строку, из которой нельзя восстановить исходный пароль.

Но мы можем снова повторить над паролем те же действия и сравнить получившиеся значения. То есть сравниваются хеши, а не исходные пароли. И в базе данных тоже хранят хеши, а после того как от клиента пришел пароль в открытом виде, вычисляют его хэш и сравнивают со значением в базе. Если они равны - значит от пользователя пришел верный пароль.

Для чего это делается? Да просто потому, что если сайт будет каким-то образом взломан, то злоумышленник в базе данных не найдёт паролей в открытом виде - только хеши. А так как из хеша получить пароль довольно сложно (при условии, что хеш-функция надежна и используется надёжный пароль), то пароль он не узнает. Следовательно:

  1. злоумышленник не сможет использовать пароль для входа на взломанный сайт;
  2. он также не сможет использовать этот пароль для входа под тем же логином и паролем в другие места (ведь довольно часто люди используют одинаковые пароли для всего).

Вычисляются хеши с помощью хеш-функции. Хеш-функции при этом вычисляют хеши следуя алгоритмам хеширования. Сейчас в PHP для хеширования следует использовать функцию password_hash(), а для проверки хеша - password_verify(). Если вы в каком-то уроке увидите, что для хеширования паролей используется md5 - бегите оттуда, такие хеши вскрываются за несколько минут, она устарела ещё лет 10 назад.

Авторизационные токены

Помимо хеша пароля в базе данных так же принято хранить так называемые авторизационные токены (AuthToken). Это комбинация символов (желательно подлиннее и с кучей кракозябр), которая генерируется при успешной авторизации пользователя и сохраняется в базе данных. А ещё она и пользователю отправляется.

И потом пользователь с помощью cookie передает этот токен на сервер, где он сравнивается со значением в базе данных. Если они равны, то считаем пользователя авторизованным. Для чего? Дело в том, что куки могут быть похищены злоумышленниками (очень многими способами, не будем об этом в этой статье, кому интересно - погуглите). И если злоумышленнику попадет в руки токен - он не сможет получить исходный пароль. О том, почему это так важно, я уже объяснил.

Заключение

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

Ах да, чуть не забыл, все исходники к каждому уроку я для вашего удобства буду выкладывать на github – вот тут.

Шаг 1. Создание базы

Первым делом создадим новую базу данных test для хранения тестовой информации. Добавьте таблицу user со следующими полями:

  • id (INT) c атрибутом AUTO_INCREMENT ;
  • name (VARCHAR(100));
  • title (VARCHAR(100));
  • address (VARCHAR(100)).

Шаг 2. Создание проекта

Создайте проект для нового приложения. В Visual Studio для этого нужно зайти в меню File > New > Project .

Создание нового проекта в Visual Studio

Создание нового проекта в Visual Studio

После этого появится окно New Project:

Окно New Project в интерфейсе Visual Studio

Окно New Project в интерфейсе Visual Studio

В поле Name нужно вписать название вашего проекта, в поле Location – указать нужную директорию, в Solution name – ввести название решения. Заполнили данные – нажимаем OK .

Главный класс нового проекта в Visual Studio

Главный класс нового проекта в Visual Studio

Шаг 3. Создание интерфейса

Создайте представление будущей формы авторизации, как показано на рисунке ниже. Добавьте два поля ( username и password ) и кнопку для входа.

Шаг 4. Настройка соединения с базой

Создайте класс connection для настройки соединения с базой. Пример реализации представлен в листинге ниже:

Шаг 5. Код авторизации

Наконец, вернитесь к форме и добавьте следующий код:

Результат

Нажмите F5 , чтобы запустить программу. Если соединение с базой данных успешно установится, вы увидите только что созданную форму.

Интерфейс работающей программы

Интерфейс работающей программы

Если при разработке сайта возникает необходимость идентифицировать пользователя, OAuth-авторизация является достаточно простым инструментом в части реализации и защищенным в части безопасности.

В публикации рассмотрена OAuth авторизация для социальных сетей Facebook, Vkontakte и аккаунтов поисковых систем Google, Yandex. Этих примеров достаточно для понимания того, что авторизация по OAuth везде одинакова, различия в реализации незначительны. А значит, полученных из публикации знаний будет достаточно для самостоятельной реализации механизма авторизации для любого другого сервиса.

Почему бы не использовать готовые библиотеки и скрипты для подключения авторизации к сайту? Потому, что:

  • OAuth авторизация достаточно проста, чтобы разобраться самому и достаточно важна, чтобы не поручать сбор персональных данных посетителей своего сайта незнакомым библиотекам,
  • гораздо быстрее раз и навсегда понять принципы OAuth авторизации, чем разбираться в каждой ошибке сторонней библиотеки при подключении очередного сервиса авторизации.

Чтобы реализовать на своем сайте OAuth авторизацию нужно:

  1. зарегистрировать свой сайт на сервере авторизации.
  2. разместить на своем сайте ссылку (кнопку), отправляющую пользователя на страницу сервера авторизации
  3. создать серверный скрипт, который будет обрабатывать результаты прохождения авторизации пользователем и, при необходимости, после успешной авторизации сохранит информацию о пользователе на сервере и перенаправит пользователя на нужную страницу сайта.

Ссылки на страницы регистрации нашего сайта:

После регистрации сайта на сервере авторизации необходимо:

запомнить для последующего использования значения параметров 'client_id', и 'client_secret';

  • для Google адрес прописывается во поле "Разрешенные URI перенаправления"
  • Yandex - "Callback URL"
  • Facebook - "URL-адрес сайта"
  • ВКонтакте - "Базовый домен"

Переход с сайта на страницу авторизации

Как правило, для перехода на страницу сервера авторизации на сайт вешается кнопка, например, так:

В качестве значения ссылки указываем адрес сервера авторизации с набором параметров Адреса на страницы авторизации

При переходе по указанным ссылкам необходимо передать следующие параметры:

  • response_type=code - (code - значение параметра для нашего случая авторизации)
  • client_id - значение присвоенное сервером авторизации при регистрации сайта
  • redirect_uri - URI адрес нашего серверного скрипта, которому будет передано управление после ввода пользователем пароля на сервере авторизации. Управление передается посредством отправки сервером скрипту GET запроса.
  • state - не обязательный, но полезный параметр. В него помещается произвольное значение. После успешной авторизации пользователем это же значение возвращается серверному скрипту в GET запросе. Например, в качестве значения этого параметра можно указать псевдоним сервера авторизации Это же значение сервер авторизации направит серверному скрипту. Таким образом, скрипт сможет идентифицировать с какого сервера авторизации пришел запрос.
  • scope указывает серверу авторизации какие дополнительные данные пользователя мы запрашиваем для нашего сайта. Пользователь при прохождении авторизации увидит какие его данные хочет получить наш сайт, соглашается с этим или отклоняет авторизацию. Обязательные данные при прохождении автризации будут возвращаться нашему сайту всегда. К обязательным данным прежде всего относится id пользователя на сервере авторизации

Из дополнительных параметров о пользователе, скорее всего, понадобится его email. поэтому в параметре scope нужно указать

Параметры для доступа к другим дополнительным параметрам пользователя можно посмотреть здесь

Обработка результатов авторизации

  1. После успешной авторизации пользователя на сервере (отказ от авторизации и неправильный ввод логина-пароля не рассматриваем) нашему скрипту обработки (URI, указанный при регистрации сайта на сервере авторизации и как параметр при переходе пользователя на страницу авторизации) направляется GET-запрос, содержащий параметр 'code' с непустым значением.
  2. Получив 'code', скрипт должен добавить его в POST-запрос серверу авторизации на получения access_token. При корректных значениях параметра нашему скрипту возвращается json-объект, содержащий в том числе и нужный acess_token
  3. Получив acess_token скрипт отправляет GET-запрос, указав значения acess_token-а в качестве параметра. Если acess_token указан правильно - сервер авторизации возвращает json объект с данными о пользователе.

Возвращаемая информация о пользователе имеет формат JSON. Однако, структура JSON, имена ключей у каждого сервера авторизации индивидуальна.

Вот и все премудрости OAuth авторизации. Осталось только написать скрипт, обрабатывающий ответы сервера авторизации. Скрипт сделаем на Python

Реализация скрипта на python

Блок 1 Настройки серверов авторизации

Для настройки ОАuth авторизации через другой сервер (не приведенный в листинге) - просто добавить соотвествующие настройки

Блок 2 Функция прохождения авторизации

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

Основная задача выполнена - пользователь идентифицировал себя через ОАuth, нужные данные о нем мы получили. Если не стоит задача куда-либо сохранять эти данные, то на этом можно остановиться.

Блок 3 Приведение данных о пользователе к единой форме

Нужно учитывать, что информация о пользователе, возвращаемая серверами авторизации имеет разные состав и структуру. Поэтому в общем случае необходимо писать отдельную функцию на каждый сервер авторизации для приведения информации к единому формату. Если на сайте планируется авторизовать пользователей через большое количество серверов, то можно применить такой прием.

Приведенный ниже способ является простым или как бы основой для создания нормальной авторизации, но его Вы вполне можете использовать, так как он достаточно хорошо работает, также Вы сами можете улучшить этот способ и внедрить у себя на сайте.

Данный способ основан на сессиях, но я здесь применяю и куки, для того чтобы браузер запоминал пользователя, который аутентифицировался прошлый раз, чтобы каждый раз не вводить логин, можно конечно хранить в куках и пароль, но это не безопасно, даже если он зашифрован. Для того чтобы сессия закончилась, просто закройте браузер и откройте заново.

Создание объектов в базе данных

Переходим к практике. Для начала создадим таблицу хранения данных о пользователях в базе MySQL. Я предлагаю использовать простую структуру таблицы (Вы ее, конечно, можете дополнить чем-нибудь, у меня база называется test, а таблица users):

И давайте сразу же добавим одну запись в эту таблицу:

Итого у нас получилось:

  • Логин – mylogin;
  • Пароль — 202cb962ac59075b964b07152d234b70;

Мы пароль, конечно же, будем хранить в хешированном виде, так как хранить пароль в открытом виде, мягко сказать, не безопасно. У нас Выше хеш пароля 123, поэтому, когда будем вводить пароль в форму, мы будем забивать именно 123, а не 202cb962ac59075b964b07152d234b70.

Создание формы регистрации

Для того чтобы пользователь мог сам зарегистрироваться, сделайте форму, данные с которой будут посылаться на файл обработки регистрации, т.е. записываться в базу данных. Например, вот самый простой способ:

Кстати, при таком способе лучше всего для логина использовать латинские буквы (т.е. английские), если хотите писать логин на русском, то придется немного корректировать код. Файл можете назвать как угодно (для теста я использовал reg.html).

Примечание! Для тестирования я использую всего один файл, я его назвал mylogin.html (код файла ниже). Вы можете использовать в своих файлах и называть их как угодно, я здесь описываю сам процесс авторизации, поэтому применить его можно везде. Кстати, во всех файлах придется использовать функцию session_start(); для того чтобы Вы могли проверять авторизован пользователь или нет. И еще один момент, конечно же, пропишите свои настройки подключения к базе данных.

Создание формы авторизации

Теперь перейдем непосредственно к самой авторизации. Создайте файл с названием mylogin.html со следующим содержанием:

Код я прокомментировал, поэтому я думаю, что все должно быть понятно. Еще раз напоминаю во всех файлах, содержимое которых Вы не хотите показывать не авторизованным пользователям, необходимо писать session_start, ну и, наверное, на этом все. Если есть вопросы, задавайте в комментариях. Удачи!

Читайте также: