Http аутентификация в php


Содержание

Аутентификация пользователя на сайте. Сессии и куки

Особенности работы протокола HTTP

Как вы узнали из прошлой главы, работа с веб-сайтами в интернете происходит по протоколу HTTP.
Это замечательный и простой протокол, который действует по схеме «запрос-ответ». То есть клиент (браузер) пользователя посылает на сервер запрос, состоящий, как правило, только из заголовков, а затем получает ответ в виде заголовков ответа и тела самого документа.
В отличие от многих других протоколов, HTTP не сохраняет своего состояния. Это означает отсутствие сохранения промежуточного состояния между парами «запрос-ответ».
Иными словами, сервер не «запоминает» клиентов; каждый запрос он обрабатывает с «чистого листа».

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

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

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

Cookies

Cookies (в дальнейшем просто «куки») — небольшие фрагменты данных, которые веб-сервер отправляет браузеру.
Браузер сохраняет их у себя, а при следующем посещении веб-страницы отправляет обратно. Благодаря этому, веб-сервер сможет узнать своего «старого» посетитеиля, идентифицировать его.

С технической стороны, куки — это обычные HTTP заголовки.
Когда веб-сервер хочет записать куку в браузер пользователя, он отсылает специальный заголовок ответа с названием Set-Cookie . В этом заголовке должна содержаться необходимая информация и дополнительные аттрибуты, о которых пойдёт речь далее.
В следующий раз, когда браузер пользователя запросит веб-страницу с того же сайта, в числе прочих заголовков он передаст заголовок запроса Cookie . Веб-сервер получит эту информацию, и она будет доступна также и для PHP.

Пример

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

Как установить куки: функция setcookie

Являясь серверным языком программирования, PHP может управлять заголовками, которые отправляет сервер, а значит может устанавливать и читать куки.
Чтобы добавить новую куку, необходимо вначале определиться со следующими критериями:

  • Название этой куки (может состоять только из символов латинского алфавита и цифр);
  • Значение, которое предполагается хранить;
  • Срок жизни куки — это обязательное условие.

За установку куки в PHP отвечает функция setcookie , ей нужно передать как минимум три параметра, описанных выше. Пример:

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

Как прочитать куки

В PHP максимально упрощён процесс чтения информации из кукисов. Все переданные сервером куки становятся автоматически доступны в специальном глобальном массиве $_COOKIE
Так, чтобы получить содержимое куки с именем «visit_count», достаточно обратиться к одноимённому элементу массива $_COOKIE , например вот так:

Обратите внимание: установив в сценарии куку через setcookie , прочитать её можно будет только при следующем посещении страницы.

Собираем всё вместе

Теперь, научившись устанавливать и читать куки, напишем полноценный сценарий, который будет считать и выводить количество посещений страницы пользователем:

Сессии

Мы уже умеем сохранять информацию для пользователя между посещениями страницы с помощью кук. Но зачем же нам ещё сессии, и для чего они нужны?
Сессии, они же сеансы, это, по сути, просто удобная обёртка над куками. Они также позволяют хранить данные, релевантные пользователю, но с некоторыми отличиями и ограничениями:

  • Данные хранятся не произвольное время, а только до закрытия вкладки с веб-страницей.
  • Чтобы сессии работали, в начале каждого сценария надо вызывать функцию session_start() .
  • Доступный объём для хранения информации намного больше.

Запись и чтение информации при использовании сессий выглядит просто как работа со специальным массивом $_SESSION .

Как устроены сессии

  1. PHP генерирует уникальный идентификатор браузера.
  2. Идентификатор сохраняется в специальную куку и передаётся с каждым запросом.
  3. Все данные, которые записываются в сессию, PHP автоматически сохраняет в специальном файле на сервере.

Благодаря существованию сессий в PHP, мы можем сохранять любые данные так же просто, как присваивать их переменным. Но, в отличие от переменных, эти данные будут сохраняться для пользователя между запросами в пределах сеанса.

Перепишем сценарий для подсчета посещений, но теперь используем сессии:

Аутентификация

Представим интернет-магазин. Все его страницы можно разделить на две половины: публичные и приватные.
К публичным относятся страницы каталога, информации о товаре, условия доставки и так далее. К приватным — корзина покупок, история заказов.
Совершенно очевидно, что корзина покупок у каждого покупателя должна быть своя, а иметь к ней доступ должен только сам владелец и никто больше.

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

  1. При попытке доступа к закрытой части сайта, пользователь видит форму, где он должен ввести свой логин и пароль.
  2. Форма отправляется, а полученные данные сравниваются с действительным логином и паролем существующего пользователя.
  3. Если данные совпадают, то пользователь считается аутентифицированным и получает доступ к приватной части сайта.
  4. При повторном открытии этой страницы пользователь не должен повторно вводить пароль, если он уже делал это в рамках текущего сеанса.

Ещё немного терминологии

Следует различать два термина: аутентификация и авторизация.

Аутентификация — проверка подлинности предоставленного пользователем идентификатора (пара логин-пароль).
Авторизация — процесс проверки и предоставления прав пользователю на выполнение определённого действия.

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

Логика авторизации намного сложнее, чем простая проверка совпадения почты и пароля при входе на сайт. В авторизацию могут также входить следующие понятия: группы пользователей, виды действий, ресурсы, иерархия ролей и действий. Этой теме можно посвятить отдельную главу. Мы не рассматриваем авторизацию в рамках этого учебника, потому что эта тема выходит за рамки «базовой».

Регистрация на сайте

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

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

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

Что такое хеширование

Отпечаток (хэш) — это результат работы функции хэширования, которая вернёт для любого значения строку фиксированной длины.
Используя специальный математический алгоритм, такая функция умеет преобразовывать любую переданную информацию к строке фиксированной длины (например, 32 или 64 символа). Причём любому массиву информации, будь это все статьи из Википедии, или одно слово, всегда будет соответствовать уникальный отпечаток. Повторный вызов функции для одного и того же исходника всегда возвращает один и тот же хэш.
Обратная операция (получить из отпечатка оригинал) невозможна.

Возьмём простой пример. У нас есть информация, для которой мы хотим получить отпечаток. Пусть такой информацией будет следующая строка:

Результат обработки этой строки хэширующей функцией SHA-1 будет таким:
6b3cb0df50fe814dee886b4e1c747dda6ce88b37

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

Реализация регистрации пользователя

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

Вызов этой функции вернёт следующую строку: $2y$10$a1pgDBerBsqD24D7qOAsl.QFTvwxQQGe4r1oWhD7f9yEnDvx4i7tW
Именно это значение и следует хранить в БД, вместо пароля.

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

После регистрации у пользователя появляется свой аккаунт на сайте, и он может его использовать. Это значит, что теперь потребуется сделать форму входа. Форма будет проверять правильность введённого логина и пароля, чтобы дать пользователю доступ к закрытым частям сайта.
Вначале мы ищем в таблице с пользователями запись с E-mail, равным полученному из формы. Если такая запись существует, то следующий шаг — это проверить корректность пароля.
Для сравнения пароля с его хэшом существует функция password_verify . Ей передаётся пароль и хэш, с которым надо сравнить данный пароль. Функция вернет true или false в зависимости от результата сравнения:

Использование сессии для контроля доступа

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

Выход с сайта

Если на сайте есть вход, то должен быть и выход. Таким выходом будет специальный сценарий, который очистит сессию и переадресует на главную страницу.
Чтобы очистить сессию, достаточно очистить массив $_SESSION :
$_SESSION = []

Выход HTTP аутентификации через PHP


Что такое правильно способ выхода из защищенной папки аутентификации HTTP?

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

17 ответов

Mu. правильного пути не существует, даже не тот, который согласован между браузерами.

это проблема, которая исходит из спецификация HTTP (раздел 15.6):

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

с другой стороны, раздел 10.4.2 говорит:

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

другими словами, вы можете снова показать поле входа в систему (as @Karsten говорит), но браузер не должен выполнять ваш запрос — Так что не зависите от этой (mis)функции слишком много.

метод, который хорошо работает в Safari. Также работает в Firefox и Opera, но с предупреждением.

это говорит браузеру открыть URL с новым именем пользователя, переопределяя предыдущий.

простой ответ заключается в том, что вы не можете надежно выйти из http-аутентификации.

длинный ответ:
Http-auth (как и остальная часть спецификации HTTP) должен быть без состояния. Таким образом, «вход в систему» или «выход из системы» на самом деле не имеет смысла. Лучший способ увидеть это-спросить для каждого HTTP-запроса (и помните, что загрузка страницы обычно состоит из нескольких запросов): «вам разрешено делать то, что вы просите?». Сервер видит каждый запрос как новый и не связанный с все предыдущие запросы.

браузеры решили запомнить учетные данные, которые вы сообщаете им на первом 401, и повторно отправить их без явного разрешения пользователя на последующие запросы. Это попытка дать пользователю модель» logged in/logged out», которую они ожидают, но это чисто kludge. Это обозреватель это имитация этого постоянства состояния. Веб-сервер об этом совершенно не знает.

Итак, «выход из системы», в контексте http-auth это чисто симуляция, предоставляемая браузером, и поэтому вне полномочий сервера.

Да, есть несколько костылей. Но они нарушают покой (если это имеет для вас ценность), и они ненадежны.

Если вам абсолютно необходима модель входа / выхода для аутентификации вашего сайта, лучше всего использовать файл cookie отслеживания с сохранением состояния, хранящегося на сервере каким-либо образом (mysql, sqlite, flatfile и т. д.). Это потребует оценки всех запросов, например, с PHP.

решение

вы можете сделать это с помощью JavaScript:

что сделано выше:

для IE — просто очистить кэш auth и перенаправить куда-то.

для других браузеров — отправить XMLHttpRequest за кулисами с «logout» имя пользователя и пароль. Нам нужно отправить его на какой-то путь, который вернет 200 OK к этому запросу (т. е. он не должен требовать Проверка подлинности по протоколу HTTP).

заменить ‘/where/to/redirect’ с некоторым путем для перенаправления после выхода из системы и замены ‘/path/that/will/return/200/OK’ С некоторым путем на вашем сайте, который вернет 200 OK.

решение (не чистый, хороший (или даже работает! см. комментарии) решение):

отключить свои учетные данные один раз.

вы можете переместить логику аутентификации HTTP на PHP, отправив соответствующие заголовки (если не вошли в систему):

и разбор входных данных с:

поэтому отключение его учетных данных один раз должно быть тривиальным.

выход из HTTP Basic Auth в два шага

предположим, у меня есть HTTP Basic Auth realm с именем «Password protected», и Боб вошел в систему. Чтобы выйти из системы, я делаю 2 запроса AJAX:

  1. скрипт доступа / logout_step1. Он добавляет случайный временный пользователь .htusers и отвечает своим логином и паролем.
  2. скрипт доступа / logout_step2 аутентификация с помощью логина и пароля временного пользователя. Скрипт удаляет временного пользователя и добавляет этот заголовок в ответ: WWW-Authenticate: Basic realm=»Password protected»

в этот момент браузер забыл учетные данные Боба.

мое решение проблемы заключается в следующем. Вы можете найти функцию http_digest_parse , $realm и $users во втором примере этой страницы:http://php.net/manual/en/features.http-auth.php.

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

Trac-по умолчанию-также использует аутентификацию HTTP. Выход из системы не работает и не может быть исправлен:

  • это проблема с самой схемой аутентификации HTTP, и мы ничего не можем сделать в Trac, чтобы исправить это должным образом.
  • в настоящее время нет обходного пути (JavaScript или другой), который работает со всеми основными браузерами.

похоже, что нет рабочего ответа на вопрос, что проблема была сообщена семь лет назад, и это имеет смысл: HTTP является апатридом. Либо запрос выполняется с учетными данными проверки подлинности, либо нет. Но это вопрос клиента, отправляющего запрос, а не сервера, получающего его. Сервер может только сказать, требуется ли URI запроса авторизация или нет.

Мне нужно было сбросить настройки .откройте файл. htaccess авторизации, так что я использовал этот:

ряд решений находятся на этой странице, и он даже отмечает внизу: Lynx, не очищает аутентификацию, как другие браузеры;)

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

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

выход из системы.в PHP

таким образом, я не получаю предупреждение, и мой сеанс прекращен

AFAIK, нет никакого чистого способа реализовать функцию «выхода» при использовании аутентификации htaccess (т. е. на основе HTTP).

Это связано с тем, что такая аутентификация использует код ошибки HTTP «401», чтобы сообщить браузеру, что требуются учетные данные, и в этот момент браузер запрашивает у пользователя подробную информацию. С этого момента, пока браузер не будет закрыт, он всегда будет отправлять учетные данные без дальнейшего запроса.

лучшее решение, которое я нашел до сих пор (это своего рода псевдо-код, $isLoggedIn является псевдо-переменной для http auth):

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

в месте, где я проверяю аутентификацию, я расширяю условие:

сеанс несколько связан с состоянием аутентификации http, поэтому пользователь остается в системе, пока он держит браузер открытым и как пока аутентификация http сохраняется в браузере.

возможно, я упускаю смысл.

самый надежный способ, который я нашел для завершения аутентификации HTTP, — закрыть браузер и все окна браузера. Вы можете закрыть окно браузера с помощью Javascript, но я не думаю, что вы можете закрыть все окна браузера.

в то время как другие правы, говоря, что его невозможно выйти из базовой аутентификации http есть способы реализовать аутентификацию, которая вести аналогично. Один очевидный appeoach-использовать auth_memcookie. Если вы действительно хотите реализовать базовую http-аутентификацию (т. е. использовать диалоговые окна браузера для входа в trather, чем HTTP — форма), используя это-просто установите аутентификацию в отдельный .защищенный каталог htaccess, содержащий PHP-скрипт который перенаправляет назад, где пользователь te пришел после создания сеанса memcache.

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

и в голове, что выход.html-страница (которая также защищена .htaccess) у меня есть обновление страницы, подобное этому:

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

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

единственный действенный способ, который я нашел, чтобы уничтожить PHP_AUTH_DIGEST или PHP_AUTH_USER и PHP_AUTH_PW учетные данные для вызова заголовка HTTP/1.1 401 Unauthorized .

Илон Маск рекомендует:  Iis о планировании пропускной способности

Простая авторизация и аутентификация на PHP в связке с MySQL

Все кто разрабатывает web сайты, рано или поздно сталкивается с такой задачей как авторизация и аутентификация пользователей, реализованная именно с помощью языка программирования, а не с помощью стандарта протокола http. Сегодня мы рассмотрим пример создания простой авторизации с использованием языка программирования PHP, а данные о пользователях будем хранить в базе MySQL.

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

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


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

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

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

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

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

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

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

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

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

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

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

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

Примечание! Если вдруг у Вас отказывает работать парсер php, т.е. на экран Вам выводится сам код php, то у Вас просто на всего не включена обработка php в файлах html. Настройки делаются в файле конфигурации web сервера httpd.conf (если apache):

В IIS в окне «Добавление сопоставления модуля» (Add Module Mapping) добавьте к *.php еще и *.html через запятую. Это если Вы делаете у себя дома на своем web сервере, а если Вы все это делаете у хостера, то Вам придется писать им и просить внести необходимые изменения, у некоторых хостеров они уже сделаны.

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

Http аутентификация в php

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

Пример 34-1. Пример HTTP-аутентификации

Замечание касательно совместимости: Будьте особенно внимательны при указании HTTP-заголовков. Для того, чтобы гарантировать максимальную совместимость с наибольшим количеством различных клиентов, слово «Basic» должно быть написано с большой буквы «B», регион (realm) должен быть взят в двойный (не одинарные!) кавычки, и ровно один пробел должен предшествовать коду 401 в заголовке HTTP/1.0 401 .

Вместо простого отображения на экране переменных PHP_AUTH_USER и PHP_AUTH_PW , вам, возможно, понадобится проверить их корректность. Используйте для этого запрос к базе данных или поиск пользователя в dbm-файле.

Вы можете пронаблюдать особенности работы браузера Internet Explorer. Он очень требователен к параметру передаваемых заголовков. Указание заголовка WWW-Authenticate перед отправкой статуса HTTP/1.0 401 является небольшой хитростью.

Начиная с PHP 4.3.0, для того, чтобы предотвратить написание кем-либо скрипта, раскрывающего пароль к странице, которая использует внешнюю аутентификацию, переменные PHP_AUTH не устанавливаются в случае, если данная страница использует внешнюю аутентификацию и установлен безопасный режим . Несмотря на это, переменная REMOTE_USER может использоваться для аутентификации пользователя, прошедшего внешнюю аутентификацию. Таким образом, вы всегда можете воспользоваться переменной $_SERVER[‘REMOTE_USER’] .

Замечание касательно конфигурации: PHP использует указание директивы AuthType для указания того, используется внешняя аутентификация или нет.

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

И Netscape Navigator и Internet Explorer очищают кеш аутентификации текущего окна для заданного региона (realm) при получении от сервера. Это может использоваться для реализации принудительного выхода пользователя и повторного отображения диалогового окна для ввода имени пользователя и пароля. Некоторые разработчики используют это для ограничения авторизации по времени или для предоставления кнопки «Выход».

Пример 34-2. Пример HTTP-аутентификации с принудительным вводом новой пары логин/пароль

function authenticate () <
header ( ‘WWW-Authenticate: Basic realm=»Test Authentication System»‘ );
header ( ‘HTTP/1.0 401 Unauthorized’ );
echo «Вы должны ввести корректный логин и пароль для получения доступа к ресурсу \n» ;
exit;
>

Это поведение не регламентируется стандартами HTTP Basic-аутентификации, следовательно, вы не должны зависеть от этого. Как показали тесты, браузер Lynx не очищает кеш авторизации при получении от сервера статуса 401, и, нажав последовательно «Back», а затем «Forward» возможно открыть такую страницу, при условии, что требуемые атрибуты авториазации не изменились. Однако, пользователь может нажать клавишу ‘_’ для очистки кеша аутентификации.

Также следует заметить, что до версии PHP 4.3.3, HTTP-аутентификация не работала на серверах под управлением Microsoft IIS, если PHP был установлен как CGI-модуль, в силу некоторых ограничений IIS. Для того, чтобы добиться корректной работы в PHP 4.3.3+, вы должны отредактировать конфигурационную настройку IIS под названием «Directory Security». Щелкните на надписи «Edit» и установите опцию «Anonymous Access», все остальные поля должны остаться неотмеченными.

Еще одно ограничение, если вы используете IIS посредством ISAPI: переменные PHP_AUTH_* не определены, но в то же время доступна переменная HTTP_AUTHORIZATION . Пример кода, который вы могли бы использовать: list($user, $pw) = explode(‘:’, base64_decode(substr($_SERVER[‘HTTP_AUTHORIZATION’], 6)));

Замечание касательно IIS:: Для того, чтобы HTTP-аутентификация корректно работала в IIS, в конфигурации PHP опция cgi.rfc2616_headers должна быть установлена значением 0 (значение по умолчанию).

The example of Digest authorization is not completely correct.

There should be:
( ‘WWW-Authenticate: Digest realm=»‘ . $realm . ‘», qop=»auth», nonce=»‘ . uniqid ( «55» ). ‘», opaque=»‘ . md5 ( $realm ). ‘»‘ );
?>
Instead of
( ‘WWW-Authenticate: Digest realm=»‘ . $realm . ‘» qop=»auth» nonce=»‘ . uniqid ( «55» ). ‘» opaque=»‘ . md5 ( $realm ). ‘»‘ );
?>

Please note the commas.

»
die(‘Text to send if user hits Cancel button’);
>

// analise the PHP_AUTH_DIGEST variable»

I think the author meant, «analyze»

A simpler approach on the post of:
bernard dot paques at bigfoot dot com
24-Sep-2004 01:42

This is another «patch» to the PHP_AUTH_USER and PHP_AUTH_PW server variables problem running PHP as a CGI.

First of all don’t forget this fragment of code in your .htaccess (it’s the only thing you need to make it work with mod_rewrite):

= base64_decode ( substr ( $_SERVER [ «REMOTE_USER» ], 6 )) ;
if ( ( strlen ( $a ) == 0 ) || ( strcasecmp ( $a , «:» ) == 0 ))
<
header ( ‘WWW-Authenticate: Basic realm=»Private»‘ );
header ( ‘HTTP/1.0 401 Unauthorized’ );
>
else
<
list( $name , $password ) = explode ( ‘:’ , $a );
$_SERVER [ ‘PHP_AUTH_USER’ ] = $name ;
$_SERVER [ ‘PHP_AUTH_PW’ ] = $password ;

echo ‘PHP_AUTH_USER =’ . $_SERVER [ ‘PHP_AUTH_USER’ ] . ‘
‘ ;
echo ‘PHP_AUTH_PW =’ . $_SERVER [ ‘PHP_AUTH_PW’ ] . ‘
‘ ;
echo ‘REMOTE_USER =’ . $_SERVER [ ‘REMOTE_USER’ ] . ‘
‘ ;
?>

First, we decode the base64 encoded string discarding the first 6 characters of «Basic » and then we do a regular validation.
At the end of the script we print the variables to verify it’s working. This should be ommited in the production version.

It’s a variation of the script by Bernard Paques.
Thanks to him for that snippet.

/**
After many tries, I created a login/logout-mechanism, which works
with Internet Explorer (tested on IE6) and Firefox (tested on V1.0).

I’ve combined some of the hints given below and used a session as
a second independent memory.

check4login() has to be called on every loading of the page.
**/

$baselink = «http://» . $_SERVER[‘HTTP_HOST’] . $_SERVER[‘PHP_SELF’];

// start a session and don’t let it stop automatically:
session_set_cookie_params(0);
session_start();
setcookie(«PHPSESSID», session_id());

// check if the current loading of the page is the first loading
// after a logout:
if ($_SESSION[‘logout’] != ») <
unset($_SESSION[‘logout’]);
//
// initialize a relogin on Firefox
// (request login with username «relogin»):
//
// CAUTION: After that, relative hyperlinks like
// Link
// will maybe translated into an absolute hyperlink like
// http://relogin:relogin@.
// which will lead to an error-message in Firefox.
//
// So you always have to use absolute hyperlinks like $baselink.
//
if (! preg_match(«/MSIE/», $_SERVER[‘HTTP_USER_AGENT’])) <
$link = preg_replace(«/^http:\/\/(.*)$/»,
«http://relogin:relogin@$1», $baselink);
header(«Location: $link»);
exit;
> >

// check if a new realm needs to be generated because
// it’s the first loading of the page (or the first loading
// after a logout):
//
// Remark: The realm is generated with some random signs,
// because Internet Explorer will forget the username if the
// realm changes. Unfortunately Firefox doesn’t do so.
if (! isset($_SESSION[‘realm’])) <
srand();
$_SESSION[‘realm’] = «My Realm «;
for ($i = 0; $i true);
echo «You were successfully logged out.»;
phpinfo(); // — for testing only
exit;
>

This forces an instant re-authentication:

// Force a logout.
function imt_logout()
<
global $_SESSION;
global $HTTP_SERVER_VARS;
global $PHP_SELF;

// We mark the session as requiring a re-auth
$_SESSION[‘reauth-in-progress’] = 1;

// This forces the authentication cache clearing
header(«WWW-Authenticate: Basic realm=\»My Realm\»»);
header(«HTTP/1.0 401 Unauthorized»);

// Check login
function imt_login()
<
global $_SERVER;
global $_SESSION;
global $REGISTERED_USERS;

// the valid_user checks the user/password (very primitive test in this example)
if (!valid_user($_SERVER[‘PHP_AUTH_USER’], $REGISTERED_USERS))
<
session_destroy();
header(«WWW-Authenticate: Basic realm=\»My Realm\»»);
header(«HTTP/1.0 401 Unauthorized»);
exit();
>

// OK, the user is authenticated
$_SESSION[‘user’] = $_SERVER[‘PHP_AUTH_USER’];
>

Assuming that your page.php?action=logout forces a reauth on the same page, start your page with:

session_start()
if ($_REQUEST[«action»] == «logout»)
<
if (isset($_SESSION[‘reauth-in-progress’]))
<
session_destroy();
header(«Location: http://».$HTTP_SERVER_VARS[‘HTTP_HOST’].$PHP_SELF);
>
else
imt_logout();
>

Don’t like passwords at home or simply don’t want access with passwords maybe told form one to another.

You make a configuration file like that:

# Passwort for special IP-Range
IP 192.168.0.
axel:PGWAiIeUxcHOg
sven:ADD1IDbsVHSEo

# Following IP works without password (Keyword ‘ALL’)
IP 192.168.0.4
ALL


# Passwords for the rest of the world
IP
ernst:INo9dSzfU5sRU
sven:ADD1IDbsVHSEo

// Konfigurationsfile einlesen:
$file = file ( $path_log );

$login = FALSE ; // Gets TRUE, when login is valid
$ip = ‘world’ ; // This is the currend IP while reading the configuration
$access = ‘world’ ; // IP from configuration fitting into $_SERVER[‘REMOTE_ADDR’]

foreach ( $file as $zeile )
<
$zeile = trim ( $zeile );

switch( true )
<
case ( strlen ( $zeile ) == 0 ): // break for empty lines
break;

case ( substr ( $zeile , 0 , 1 ) == ‘#’ ): // break for Komments
break;

case ( substr ( $zeile , 0 , 2 ) == ‘IP’ ): // change IP range
$ip = substr ( $zeile , 3 );
if ( $ip == » )
$ip = ‘world’ ;

if ( ereg ( «^$ip» , $_SERVER [ ‘REMOTE_ADDR’ ]) ) // fitting IP
<
$access = $ip ;
>
break;

case ( ereg ( «(.+):(.*)» , $zeile , $reg ) ): // scan passwords
$logray [ $ip ][ $reg [ 1 ]] = $reg [ 2 ];
break;

case ( $zeile == ‘ALL’ ): // if no login is needet
$logray [ $ip ][ ‘all’ ] = 1 ;
>
>

//
if ( isset( $_GET [ ‘logout’ ]) )
<
unset( $_SERVER [ ‘PHP_AUTH_USER’ ]);
unset( $_SERVER [ ‘PHP_AUTH_PW’ ]);
>
//

// authorisation test
if ( isset( $_SERVER [ ‘PHP_AUTH_USER’ ]) AND isset( $_SERVER [ ‘PHP_AUTH_PW’ ]) )
if( isset( $logray [ $access ][ $_SERVER [ ‘PHP_AUTH_USER’ ]]) )
if( $logray [ $access ][ $_SERVER [ ‘PHP_AUTH_USER’ ]] == crypt ( $_SERVER [ ‘PHP_AUTH_PW’ ], ( substr ( $logray [ $access ][ $_SERVER [ ‘PHP_AUTH_USER’ ]], 0 , 2 ))) )
$login = TRUE ;

if ( isset( $logray [ $access ][ ‘all’ ]) )
$login = TRUE ;

// send login-form if needet
if ( ! $login )
<
Header ( «WWW-Authenticate: Basic realm=\»Test Authentication System\»» );
Header ( «HTTP/1.0 401 Unauthorized» );
echo «You must enter a valid login ID and password to access this resource\n» ;
exit;
>

// Your running programm.
if ( $login )
<
echo «Hello » . $_SERVER [ ‘PHP_AUTH_USER’ ];

The approach described in the manual works only at servers where PHP is ran as an Apache module. Where PHP is ran as a CGI module, credentials are always empty, whether the user actually fills the authentication box or not.

Apparently the set of Apache variables exposed to PHP is restricted when PHP runs in CGI mode, and this explains why $_SERVER[‘PHP_AUTH_USER’] and $_SERVER[‘PHP_AUTH_PW’] are not set.

The solution is to select one Apache variable actually transmitted to PHP even in CGI mode, and to put in it authentication data submitted by the browser.

Look at the following directive added to the .htaccess file:

This directive states that, if mod_rewrite is available, credentials gathered from the HTTP header Authorization are put into the $_SERVER[‘REMOTE_USER’] variable.

To build up on RFC 2617 on HTTP Authentication, if the surfer wishes to send the userid «Aladdin» and password «open sesame», the browser will add the following header attribute to the HTTP request:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Thanks to the rewrite directive put in .htaccess, the triggered PHP script will catch credentials through $_SERVER[‘REMOTE_USER’] as follows:

$_SERVER[‘REMOTE_USER’] = Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

From there all you have to do is to decode base64 credentials, and to split the string to retrieve user name and password, as described into the RFC 2617.

Before you use $_SERVER[‘PHP_AUTH_USER’] and $_SERVER[‘PHP_AUTH_PW’], check if these variables are empty.

If yes, attempt to rebuild them by using $_SERVER[‘REMOTE_USER’].

The following snippet does exactly that:

// maybe we have caught authentication data in $_SERVER[‘REMOTE_USER’]
if((! $_SERVER [ ‘PHP_AUTH_USER’ ] || ! $_SERVER [ ‘PHP_AUTH_USER’ ])
&& preg_match ( ‘/Basics+(.*)$/i’ , $_SERVER [ ‘REMOTE_USER’ ], $matches )) <
list( $name , $password ) = explode ( ‘:’ , base64_decode ( $matches [ 1 ]));
$_SERVER [ ‘PHP_AUTH_USER’ ] = strip_tags ( $name );
$_SERVER [ ‘PHP_AUTH_PW’ ] = strip_tags ( $password );
>
?>

The full script used to build a secured RSS feed is available here:

Of course, this trick works only if the mod_rewrite module is available, and if you have changed the .htaccess file as explained above.

on the php+mysql auth code by tigran at freenet dot am

There are some security weaknesses.

are both insecure, they could leave this code open to SQL injection, you should always remove invalid characters in both, or at least encode them.

Actually storing passwords as MD5 hashes leaves you less work to secure.

Second security risks
The same mysql user has rights to both update and select, and possibly even insert and on your auth database no less.
Again the SQL inject attack may occur with this., and the end user could then change the users username, password, or anything else in relation to this.

Third items is more of a performance issue,

Do you really need to update the database, as updates are slower then selects, and if you do them every time they access the page, you are costing some speed penalty.

One option, if you want to use sql (I think mysql has it) is memory only databases, and create a table within memory, the stores a unique session identifier for each user, that is logged in, or alternatively if it’s a single front end system, you could use db files.

Note that Microsoft has released a ‘security update’ which disables the use of username:password@host in http urls.

You can re-enable this functionality as described at

but your users will probably be unwilling to do this.

A simple script for SSL Client Certificate authentication with a basic authentication fall-back. I use this on my site using LDAP server to check username/passwords and client certificate to user mapping.

// Check if and how we are authenticated
if ( $_SERVER [ ‘SSL_CLIENT_VERIFY’ ] != «SUCCESS» ) < // Not using a client certificate
if ((! $_SERVER [ ‘PHP_AUTH_USER’ ]) && (! $_SERVER [ ‘PHP_AUTH_PW’ ])) < // Not logged in using basic authentication
authenticate (); // Send basic authentication headers
>
>

if ( $_SERVER [ ‘SSL_CLIENT_S_DN_CN’ ] != «chris» ) < // Check CN name of cert

if (!(( $_SERVER [ ‘PHP_AUTH_USER’ ] == «test» ) && ( $_SERVER [ ‘PHP_AUTH_PW’ ] == «123» ))) < // Check username and password
authenticate (); // Send basic authentication headers because username and/or password didnot match
>
>

// Call authentication display
function authenticate () <
Header ( «WWW-Authenticate: Basic realm=Website» );
Header ( «HTTP/1.0 401 Unauthorized» );
error401 ();
exit;
>
?>

See my website (http://www.schaake.nu/index.php?page=/manuals/sslmanual.xml) for more details on client certificate with Apache and PHP.

There is a nice way to ‘fix’ missing REMOTE_USER env variable when using PHP as CGI, using mod_rewrite rule like this:

Quite a good solution for the logout problem:

Just tell browser that it is successfully logged in!
This works as follows:
1. User clicks logout button
2. Script sends 401 Header
3. User does NOT enter a password
4. If no password is entered, script sends 200 Header

So the browser remembers no password as a valid password.

In my use of HTTP Authentication, I’ve found that some Apache setups swap around the usual variables.
Here’s the fix I made so that you can still use PHP_AUTH_USER and PHP_AUTH_PW. Hope it helps someone

Regarding HTTP authentication in IIS with the php cgi 4.3.4, there’s one more step. I searched mightily and didn’t find this information anywhere else, so here goes. When using HTTP auth with the php CGI, you need to do the following things:

1. In your php.ini file, set «cgi.rfc2616_headers = 0»

2. In Web Site Properties -> File/Directory Security -> Anonymous Access dialog box, check the «Anonymous access» checkbox and uncheck any other checkboxes (i.e. uncheck «Basic authentication,» «Integrated Windows authentication,» and «Digest» if it’s enabled.) Click OK.

3. In «Custom Errors», select the range of «401;1» through «401;5» and click the «Set to Default» button.

It’s this last step that is crucial, yet not documented anywhere. If you don’t, instead of the headers asking for credentials, IIS will return its own fancy but useless ‘you are not authenticated’ page. But if you do, then the browser will properly ask for credentials, and supply them in the $_SERVER[‘PHP_AUTH_*’] elements.

Say you have password and groups files in standard Apache format (htpasswd etc.), but you want to apply authorization based on something other than filename, ie something you can’t catch in .htaccess. You want to emulate the server behavior in PHP — the equivalent of:

AuthType Basic
AuthName «Members»
AuthUserFile /path/to/.htpasswd
AuthGroupFile /path/to/.groups
require group Members

Here’s what I came up with:

= file ( «/path/to/.htpasswd» );
$AuthGroupFile = file ( «/path/to/.groups» );
$group = «Members» ;
$realm = «Members» ;

function authenticate () <
header ( «WWW-Authenticate: Basic realm= \» $realm \» » );
header ( ‘HTTP/1.0 401 Unauthorized’ );
echo «You must enter a valid user name and password to access the requested resource.» ;
exit;
>

for(; 1 ; authenticate ()) <
if (!isset( $HTTP_SERVER_VARS [ ‘PHP_AUTH_USER’ ]))
continue;

$user = $HTTP_SERVER_VARS [ ‘PHP_AUTH_USER’ ];
if(! preg_grep ( «/$group: $user $ /» , $AuthGroupFile )) # (format assumptions)
continue;


if(!( $authUserLine = array_shift ( preg_grep ( «/$user:.* $ /» , $AuthUserFile ))))
continue;

preg_match ( «/$user:((..).*) $ /» , $authUserLine , $matches );
$authPW = $matches [ 1 ];
$salt = $matches [ 2 ];
$submittedPW = crypt ( $HTTP_SERVER_VARS [ ‘PHP_AUTH_PW’ ], $salt );
if( $submittedPW != $authPW )
continue;

echo «You got in!»
?>

Here is a extremely easy way to successfully logout.

Илон Маск рекомендует:  Memchr   memset работа с байтами в массивах

if ( $realm == » )
$realm = mt_rand ( 1 , 1000000000 );
header ( ‘WWW-Authenticate: Basic realm=’ . $realm );
?>

To log the user out simply change the value of $realm

Hi there. Thought long and hard to come up with a logout mechanism that erases the variables $PHP_AUTH_USER and $PHP_AUTH_PW. Finally came up with something, it is better than nothing, hope somebody will find it usefull:

( «Location: http://EnterYourUserName:YourPassword@ServerRoot» . $PHP_SELF );
exit;
?>

«EnterYourUserName» and «YourPassword» will be the two variables new value, while «ServerRoot» is your server’s domainname (like www.somedomain.com).
You should ensure, that nobody will use «EnterYourUserName» as it’s login name.

Modified script from «jonhaynes at bigfoot dot com» using Oracle logon

function authenticate () <
header ( «WWW-Authenticate: Basic realm=\»My Realm\»» );
header ( «HTTP/1.0 401 Unauthorized» );
print( «You must enter a valid login username and password
to access this resource.\n» );
exit;
>

if(!isset( $_SERVER [ ‘PHP_AUTH_USER’ ]))< authenticate (); >
else <
$conn = @ OCILogon ( $_SERVER [ ‘PHP_AUTH_USER’ ], $_SERVER [ ‘PHP_AUTH_PW’ ], «orcl92» ) ;
if(! $conn )
< authenticate (); >
else < OCILogoff ( $conn );>;
>
?>

The method described in the text does not appear to work with PHP in cgi mode and Apache-2.x. I seems that Apache has gotten stricter or introduced a bug such that you can initiate the authentication, but Apache seems to try to authenticate the browser response which always fails because it does not know what to authenticate against and the headers never get passed back to the PHP script.

I didn’t try it with PHP as a module.

To clear HTTP authentication cache in Internet Explorer (6 SP1 and later), use «ClearAuthenticationCache» command.

Some servers won’t support the HTTP1.0 specification and will give an error 500 (for instance). This happened with a server where I uploaded an authentication script.

If it happens, you can try the HTTP1.1 header syntax :

( «WWW-Authenticate: Basic realm=\»My Realm\»» );
header ( ‘status: 401 Unauthorized’ );
?>

Here is my solution — works in MSIE and Mozilla.

I use http-authentication only for the first time user accesses his
private page; after valid username and password are provided, he is
recognized using his sessionID and ip .
the reasons are following:
1) when users changes his password it is not required instantly
(I find this quite comfortable)
2) auto-login function works fine (unless user click logout)

And here’s how i works .

The «trick» is to pass a temporary username+password to the browser.
(I call it «temporary» because no user account matching these
parameters is neccessary.)

The most essential thing is the following link on user’s private page:

===
= «http://» .
$username . // see note 1
«:» .
Session_ID (). // see note 2
«@localhost/» . PROJECT_NAME . «/logout.phtml» ;
?>
«>logout
===

1) we pass the actual username because MSIE uses this username as
a «default pre-fill» for the login-window and some hash-string
would confuse the users.
2) the temporary password is not too important, but there are
two things we expect from it:
a) we need to know this string in the logout.phtml script
b) the string definetely should not match the user’s password
(otherwise user gets logged back instantly); using current
Session_ID() we are pretty sure this won’t happen

This link causes that the temporary login-params are available in
the logout.phtml script.
Using «www-authenticate» header in the logout.phtml script we force
the browser to accept our temporary login-params. (I suppose browser
actually repeats the request and the next time it checks
the login-params sent in the URL; but this is only my guess and
it is not important.)

The logout.phtml code:
===
= «UPDATE users SET session > .
«WHERE session > . Session_ID (). «‘» ;
$mysql -> query ( $query );
// because we (me :o) use the sessionID and the ip for
// the identification we need to clean the sessionID; (I found it
// a little bit easier to destroy the sessionID in the db than
// unsetting the cookie and/or destroying+restarting
// the current session)

if( $PHP_AUTH_PW != Session_ID ()) <
// keep asking for the login-params untill PHP_AUTH_PW returned
// by the browser matches the current Session_ID() (which means
// that the browser accepted the temporary login-params
// we sent to it AND FORGOT THE REAL ONES)

Отправитель аутентификации HTTP через PHP

Каков правильный способ выхода из защищенной папки проверки подлинности HTTP?

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

Mu. Не существует правильного пути , даже не совместимого с браузерами.

Это проблема, вытекающая из спецификации HTTP (раздел 15.6):

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

С другой стороны, в разделе 10.4.2 говорится:

Если запрос уже включил учетные данные авторизации, то ответ 401 указывает, что для этих учетных данных было отказано в авторизации. Если ответ 401 содержит ту же задачу, что и предыдущий ответ, и пользовательский агент уже попытался выполнить аутентификацию хотя бы один раз, тогда пользователю ДОЛЖЕН быть представлен объект, который был указан в ответе, поскольку этот объект может содержать соответствующую диагностическую информацию.

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

Метод, который хорошо работает в Safari. Также работает в Firefox и Opera, но с предупреждением.

Это говорит браузеру, чтобы открыть URL с новым именем пользователя, переопределяя предыдущий.

Простой ответ заключается в том, что вы не можете надежно выйти из http-аутентификации.

Длинный ответ:
Http-auth (как и остальная часть спецификации HTTP) означает быть апатридом. Таким образом, «вход в систему» ​​или «выход из системы» на самом деле не является концепцией, которая имеет смысл. Лучший способ увидеть это – спросить, для каждого HTTP-запроса (и помните, что загрузка страницы обычно представляет собой несколько запросов), «разрешено ли вам делать то, что вы запрашиваете?». Сервер видит каждый запрос как новый и не связан с любыми предыдущими запросами.

Браузеры решили запомнить учетные данные, которые вы им сообщаете в первых 401, и повторно отправить их без явного разрешения пользователя на последующие запросы. Это попытка предоставить пользователю «зарегистрированную / выведенную» модель, которую они ожидают, но это просто kludge. Это браузер, который имитирует это сохранение состояния. Веб-сервер полностью не знает об этом.

Таким образом, «выход из системы», в контексте http-auth – это просто симуляция, предоставляемая браузером, и, таким образом, вне полномочий сервера.

Да, есть клоды. Но они ломают RESTful-ness (если это ценно для вас), и они ненадежны.

Если для аутентификации вашего сайта вам абсолютно необходима модель входа в систему / выходила из системы, лучшим вариантом является файл cookie отслеживания с сохранением состояния, хранящегося на сервере каким-либо образом (mysql, sqlite, flatfile и т. Д.). Это потребует оценки всех запросов, например, с помощью PHP.

Временное решение

Вы можете сделать это, используя Javascript:

Что сделано выше:

для IE – просто очистить кеш кеша и перенаправить куда-нибудь

для других браузеров – отправьте XMLHttpRequest за кулисами с именем входа и паролем logout. Нам нужно отправить его на какой-то путь, который вернет 200 OK к этому запросу (т. Е. Он не должен требовать HTTP-аутентификации).

Замените ‘/where/to/redirect’ на какой-то путь для перенаправления после выхода из системы и замените ‘/path/that/will/return/200/OK’ на какой-то путь на вашем сайте, который вернет 200 OK.

Обходное решение (не чистое, приятное (или даже работающее! См. Комментарии) решение):

Отключите его учетные данные один раз.

Вы можете переместить логику проверки подлинности HTTP на PHP, отправив соответствующие заголовки (если они не вошли в систему):

Поэтому отключение его учетных данных один раз должно быть тривиальным.

Выход из HTTP Basic Auth за два шага

Предположим, что у меня есть базовое пространство HTTP с именем «Защита паролем», и Боб вошел в систему. Чтобы выйти из системы, я делаю 2 запроса AJAX:

  1. Скрипт доступа / logout_step1. Он добавляет случайного временного пользователя в .htusers и отвечает своим логином и паролем.
  2. Скрипт доступа / logout_step2 аутентифицирован с использованием логина и пароля временного пользователя . Сценарий удаляет временного пользователя и добавляет этот заголовок в ответ: WWW-Authenticate: Basic realm=»Password protected»

В этот момент браузер забыл учетные данные Боба.

Мое решение проблемы заключается в следующем. Вы можете найти функцию http_digest_parse , $realm и $users во втором примере этой страницы: http://php.net/manual/en/features.http-auth.php .

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

Trac – по умолчанию – использует HTTP-аутентификацию. Выход из системы не работает и не может быть исправлен:

  • Это проблема с самой схемой аутентификации HTTP, и мы ничего не можем сделать в Trac, чтобы исправить ее правильно.
  • В настоящее время нет обходного пути (JavaScript или другого), который работает со всеми основными браузерами.


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

Мне нужно было сбросить авторизацию .htaccess, поэтому я использовал это:

Ряд решений находится на этой странице, и он даже отмечает внизу: Lynx, не очищает auth, как другие браузеры;)

Я тестировал его на установленных браузерах и когда-то закрывался, каждый браузер, похоже, постоянно требует повторного запуска.

Это может быть не решение, которое нужно было искать, но я решил это так. У меня есть 2 скрипта для процесса выхода.

Таким образом, я не получаю предупреждение, и моя сессия прекращается

AFAIK, нет чистого способа реализовать функцию «выхода» при использовании аутентификации htaccess (т.е. на основе HTTP).

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

Лучшее решение, которое я нашел до сих пор (это своего рода псевдокод, $isLoggedIn является псевдо переменной для http auth):

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

В том месте, где я проверяю подлинность, я расширяю условие:

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

В то время как другие верны, говоря, что невозможно выйти из базовой HTTP-аутентификации, есть способы реализовать аутентификацию, которая ведет себя аналогичным образом. Одно очевидное обращение – использовать auth_memcookie . Если вы действительно хотите реализовать базовую HTTP-аутентификацию (т. Е. Использовать диалоговые окна браузера для входа в trather, чем HTTP-форму), используя это – просто установите аутентификацию в отдельный .htaccess защищенный каталог, содержащий скрипт PHP, который перенаправляет обратно туда, куда пришел пользователь создание сеанса memcache.

Может быть, мне не хватает смысла.

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

Здесь много замечательных ответов. В моем конкретном случае я нашел чистое и простое исправление для выхода из системы. Мне еще предстоит проверить в Edge. На моей странице, на которой я вошел, я разместил ссылку для выхода из системы, подобную этой:

И в голове этой страницы logout.html (которая также защищена .htaccess), у меня есть обновление страницы, похожее на это:

Если вы оставите слова «logout» на месте, чтобы очистить имя пользователя и пароль, кэшированные для сайта.

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

Единственный эффективный способ, с помощью которого я смог уничтожить учетные данные PHP_AUTH_DIGEST или PHP_AUTH_USER и PHP_AUTH_PW – это вызвать заголовок HTTP/1.1 401 Unauthorized .

Защищенная Авторизация и Регистрация на PHP + MySQL через PDO

В этой статье Вы найдете скрипт на языке программирования PHP, который позволяет пользователю зарегистрироваться и авторизоваться на сайте. Скрипт на 100% защищает от SQL-инжекций, поскольку использует PDO (система подготовленных запросов) и библиотеку RedBeanPHP, которая реализует ORM. Использовать RedBeanPHP мы будем только, чтобы присоединиться к базе данных и легко ей манипулировать, не используя стандартные команды в PHP, такие как mysql_connect и подобные, потому что они устаревшие и не очень эффективные.

Скрипт использует сессии ($_SESSION) и позволяет узнать авторизован сейчас человек или нет. Также в скрипте предусмотрена капча с рандомными вопросами, которая защищает сайт от надоедливого спама.

Скрипт состоит из следующих файлов:

  • index.php — содержит 2 ссылки (на форму авторизации и регистрации);
  • rb.php — ORM-библиотека RedBeanPHP;
  • db.php — подключение к базе данных;
  • login.php — обработчик авторизации пользователя и форма авторизации;
  • signup.php — обработчик регистрации пользователя и форма регистрации;
  • logout.php — выход из сессии.

Как подключить скрипт?

Скачайте готовый скрипт и перенесите все файлы на свой хостинг или локальный сервер (Denwer, OpenServer). Для работы скрипта Вам потребуется версия PHP не ниже 5.6. Далее необходимо создать базу данных и подсоединиться к ней. Для этого потребуется поменять значения в файле db.php. Если с этим возникнут трудности, то Вы можете задавать свои вопросы в комментариях под статьей.

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

В файле login.php находится обработчик и сама форма авторизации, которая состоит из двух полей (логин, пароль). Значок @ (собачка) перед переменными служит в PHP для отключения ошибки, если такая возникнет.

PHP обработчик формы авторизации пользователя

Все переменные, которые возвращаются по методу POST — мы присваиваем переменной $data.

Форма регистрации

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

PHP обработчик формы регистрации пользователя

Смотреть видеоурок

Статья была написана на основе видеоурока Хауди Хо, который Вы можете посмотреть ниже. Скрипт из видео был немного доработан (добавлена капча function captcha_show).

аутентификация — PHP HTTP базовая авторизация Выйти

Я использовал базовую аутентификацию PHP при входе в систему.

И теперь я должен добавить выход на нашем сайте.

Я использую глобальную переменную для вычисления времени, и я возвращаю 401 ошибку после указанного времени.

Это похоже на выход из системы.

Но если пользователь нажимает кнопку отмены в окне аутентификации и обновляет ( F5 ), аутентификация прошла успешно.

Хотя я пытался удалить PHP_AUTH_USER но когда пользователь обновляет веб-браузер PHP_AUTH_USER все еще установлено.

Как сделать авторизацию на PHP? Пишем авторизацию пользователя

В этой статье вы узнаете, как сделать PHP-авторизацию (authentication) на сайте с помощью данных, полученных от пользователя при регистрации. Будем использовать таблицу MySQL, а сама PHP-авторизация будет работать с применением сессий и cookie. Материал не следует рассматривать, как пошаговое руководство. Зато он помогает понять, как работает PHP-авторизация в целом.

В первую очередь нужно сверстать главную страницу веб-сайта, поместив её в корне в папку template. Для этого создаём файл index.html с формой ввода логина и пароля, кнопкой «Вход», вот её код:

Мы используем метод передачи post, который необходим. Нам ведь не нужно, чтобы в процессе PHP-авторизации пароль и логин «светились» в адресной строке.

Когда форма готова, создаём главный контроллер — наиболее важный файл сайта, лежащий в корне — index.php. Как раз он и будет запускаться во время входа. Код выглядит следующим образом:

Теперь разберёмся подробнее, как всё работает.

В первых 3 строках просто подключаются файлы с функциями, необходимыми для дальнейшего использования в коде. О них поговорим потом. Далее проверяем, был ли передан get-параметр action=out . В случае его передачи пользователь нажал на ссылку выхода с веб-сайта. Код ссылки, который нужно добавить в файл, содержащий код формы для входа:

Потом у нас идёт условие, которое проверяет, авторизован ли ты (if (login())). То есть функция возвращает нам true, если юзер вошёл на сайт. В противном случае возвращается false. Когда вернулось true, в переменную $UID записывается id юзера. Что касается переменной $admin, то в неё пишется результат работы функции is_admin($UID) . Она определяет, является ли наш юзер админом, возвращая true, если это так и false в обратном случае. Потом эти 2 переменные понадобятся, чтобы вывести определённые элементы на странице.

Итак, форму PHP-авторизации можно вывести следующим условием:

Аналогичная ситуация и с переменной $admin. Последний код тоже можно поместить в файл с формой.

Если функция login() вернёт false (юзер не вошёл на сайт), мы проверим, а нажал ли он вообще на кнопку входа на сайт, которая включена в нашу форму PHP-авторизации:

Если это так, запускается функция enter() , авторизующая пользователя. Если ошибки отсутствуют, а пользователь вошёл успешно, создаём те же две переменные: $UID и $admin. В обратном случае переменные не создаются никакие, ведь пользователь является гостем.

Давайте посмотрим на алгоритм работы:

А теперь рассмотрим все функции, вызываемые в коде. Вот функция входа на сайт:

Сначала функция проверит, а заполнено ли поле для ввода пароля и логина для PHP-аутентификации. Если да, работа программы продолжается, в противном случае в массив $error пишется текст ошибки, и происходит возвращение в основную программу, которая после того, как узнает размерность полученного массива, пользователя не авторизует.

Но если работа функции enter() будет продолжена, мы проверим, а существует ли в базе данных запись с таким ником. Когда записи нет, возвращается массив с ошибкой. Когда есть, введённый пароль сравнивается со значением, которое хранится в БД.

Пароли сравниваются не в чистом виде, т. к. в базе данных они хэшированы функцией md5() . Значит это следующее: прежде чем приступить к сравнению, нужно хэшировать тем же алгоритмом пароль, введённый пользователем при попытке пройти аутентификацию/авторизацию.

Когда хэши совпадают, происходит авторизация с помощью скрипта. При отсутствии совпадений, возвращается ошибка.

Давайте подробно остановимся на том, что значит «авторизироваться». В нашем скрипте информация о PHP-авторизации хранится в cookie и сессии. В сессию записывается id пользователя:


Кроме того, создаются 2 cookie: login и password. Продолжительность жизни — 50 тыс. секунд. В первый пишется логин, во 2-й — хэш пароля.

В данной строке выполняется функция, которая устанавливает время последней активности юзера. Код:

С помощью функции перезаписываются поля online и last_act в базе данных. Здесь, кстати, важно убедиться, что эти поля существуют (оба имеют тип int).

Теперь посмотрим на алгоритм работы функции enter() :

Идём дальше. Следующая функция нужна для проверки, авторизирован ли юзер на сайте — login() .

Возникает вопрос, почему для авторизации используем и сессию, и cookie? Всё дело в том, что при закрытии браузера сессия «умирает», а пользователь автоматически разлогинивается. А вот cookie хранятся определённое время, задаваемое нами (50 тыс. секунд).

Дальше у нас функция online() . Её нужно запускать первой на всех модулях и страницах будущего сайта. В первую очередь, она проверяет, прошёл ли пользователь PHP-авторизацию/аутентификацию, что важно для дальнейшей работы скрипта. Во вторую очередь, она выполняет обновление времени последней активности, а также помогает в перспективе выводить систему онлайн-пользователей.

Наша функция вернёт true, когда юзер авторизирован, а в обратном случае — false. При этом в процессе работы обновится время жизни cookie или они будут созданы, если вообще не существуют.

Илон Маск рекомендует:  Введение в xajax

Очередной алгоритм работы:

Когда есть сессия и cookie, обновляется время жизни cookie. Чтобы это реализовать, они удаляются, время смерти устанавливается на одну секунду раньше текущего времени, потом устанавливаете заново. Также нужно учесть, что функция lastAct() обновляет время последней активности. Возвращается, разумеется, true.

Когда сессия есть, а cookie почему то нет, то по id юзера мы получаем из базы данных логин и хэш пароля, потом пишем их в cookie. Возвращается true.

Когда сессии нет, проверяем, существуют ли cookie. Традиционный пример — PHP-авторизация после перезапуска браузера, когда сессия слетела, но cookie всё ещё живы. Становится сложнее, ведь нужно проверить, а совпадает ли пара пароль-логин с какой-нибудь строкой из базы данных. Ведь пользователь легко мог сменить cookie в настройках для сайта. Если пара нашлась, создаётся переменная сессии, возвращается true. Если пара не нашлась, возвращается false.

Если у нас самый печальный вариант — ни сессии, ни cookie не оказалось, возвращается false.

Сейчас глянем на функцию is_admin($UID) , определяющую является ли user админом. Если вам это не надо, опустите данную функцию и её вызовы в контроллере. Но учтите, что для вывода контента на страницу для админов она бывает полезна. К тому же, она проста и основана на одном столбце в базе данных в таблице users (столбец prava, тип int).

Когда наш юзер обыкновенный пользователь, значению в столбце присваивается 0, иначе — 1. Соответственно, в первом случае вернётся false, во втором — true.

Последняя функция — это out() . Она проста и удаляет все «следы» юзера — и сессию, и cookie.

Код всех наших функций нужно поместить в файл lib/module_global.php, подключаемый в начале работы контроллера.

Итак, мы написали функциональную, но простую PHP-регистрацию/аутентификацию/авторизацию для сайта. Также заложили фундамент для дальнейших возможностей по администрированию и не только. Такая PHP-авторизация не слетит после перезапуска браузера, т. к. мы используем cookie. Предусмотрен и выход с сайта.

Аутентификация и авторизация с использованием Auth0 в PHP

Russian (Pусский) translation by Dima (you can also view the original English article)

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

Что такое Auth0?

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

Позвольте мне кратко изложить, что Auth0 может предложить:

  • единый вход в систему
  • многофакторная аутентификация
  • вход в систему без пароля
  • Управление пользователями
  • и многое другое

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

В первой половине статьи мы рассмотрим, как настроить базовую функцию аутентификации в веб-приложении на стороне сервера. Во второй половине я объясню, как вы можете защитить свои пользовательские API, установив авторизацию OAuth с помощью службы Auth0.

Интеграция аутентификации на стороне сервера

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

Прежде чем двигаться вперед, обязательно установите Composer, поскольку он будет использоваться для установки фактических SDK Auth0 с использованием файла composer.json . Кроме того, если вы хотите следовать вместе с примерами в этой статье, продолжайте и получите бесплатную учетную запись с Auth0.

Настройка проекта

Давайте двигаться вперед и захватим копию образцов проекта.

Для установки зависимостей выполните команду composer install .

Согласно файлу composer.json, он должен был установить пакеты vlucas/phpdotenv и auth0/auth0-php .

Библиотека vlucas/phpdotenv используется для инициализации переменных среды из файла .env. Таким образом, он позволяет отделить конфигурацию от кода, который изменяется между средами.

С другой стороны, пакет auth0/auth0-php является тем, который поможет нам настроить авторизацию в нашем приложении.

Далее, давайте настроим конфигурацию нашего приложения в файле .env. Идем дальше и создаем файл .env, копируя его из файла .env.example.

Он содержит значения конфигурации, которые будут использоваться библиотекой Auth0.

Вы должны найти большинство настроек в разделе Приложения> Стандартное приложение> Настройки на панели управления Auth0. Обратите внимание, что я использую приложение по умолчанию, созданное системой. Конечно, вы можете пойти и создать новое приложение, если хотите это сделать.

AUTH0_CALLBACK_URL — это URL вашего приложения, в котором Auth0 будет перенаправлять пользователей после входа в систему и выхода из системы. Значение, заданное в этом поле, должно быть настроено в разделе « Разрешенные обратные вызовы » в настройках приложения на панели управления Auth0.

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

  • index.php: Это основная страница, на которой отображается кнопка входа или выхода из системы на основе состояния пользователя.
  • login.php: этот скрипт будет инициирован, когда вы нажмете кнопку входа в систему, и перенаправит пользователей на интерфейс входа Auth0 для входа. После входа в систему они будут перенаправлены обратно на AUTH0_CALLBACK_URL .
  • logout.php: этот скрипт будет инициирован, когда вы нажмете кнопку выхода из системы, и перенаправит пользователей на Auth0 в фоновом режиме, выйдет из системы и вернет их обратно на AUTH0_CALLBACK_URL .

Файлы проекта

Давайте быстро рассмотрим каждый файл в стартовом проекте.

Login-Script

Мы начнем с файла login.php.

Вначале мы включили автозагрузчики, которые отвечают за загрузку классов, связанных с переменной Auth0 и средой. После этого мы инициализируем конфигурационные переменные из файла .env, используя функцию getenv .

Затем мы создаем экземпляр объекта Auth0 и вызываем метод входа, который перенаправляет пользователей на Auth0 для входа. После входа в систему пользователи будут перенаправлены на наш сайт.

Вы можете войти в систему, используя свои социальные учетные записи, такие как Facebook, Google и т. д., Или создать новую учетную запись при входе в систему. В любом случае Auth0 создаст записи для новых пользователей на своем конце. Вы можете включить различные социальные входы в разделе «Подключения»> «Социальные» на панели управления Auth0. Кроме того, вы можете проверить список пользователей, которые вошли в систему, используя Auth0 на панели управления Auth0 в разделе «Пользователи».

Сценарий выхода

Затем давайте быстро взглянем на файл logout.php.

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

Индексный файл

Наконец, давайте рассмотрим файл index.php, который является точкой входа нашего приложения.

Здесь мы использовали метод getUse r объекта $auth0 , чтобы узнать, есть ли какой-либо активный сеанс. Если активного сеанса нет, мы отобразим ссылку «Вход», которая приведет пользователя к login.php и инициирует поток входа. С другой стороны, мы приветствуем пользователя и показываем ссылку «Выход», если пользователь уже вошел в систему.

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

Защитите свои пользовательские API с помощью OAuth2

В этом разделе мы рассмотрим, как вы можете защитить свои пользовательские API, выполнив поток предоставления кода авторизации OAuth2. Надеюсь, вы знакомы со стандартным потоком предоставления кода авторизации, так как мы не будем вдаваться в подробности этого. Ознакомьтесь с некоторыми нашими другими сообщениями здесь, на Envato Tuts +, если вы хотите ускориться с OAuth2.

Аутентификация с помощью PHP и MySQL.

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

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


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

Листинг 6.11. secret.php — РНР-код для реализации простого механизма аутентификации

Please Log In

echo «You are not authorized to view this resource.»; >

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

· поддерживает только одно жестко закодированное имя пользователя и пароль

· хранит пароль в виде простого текста

· защищает только одну страницу

· передает пароль в виде простого текста

Упомянутые проблемы можно разрешить с различной степенью усилий и успеха.

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

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

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

Сценарий для аутентификации посетителей страницы с использованием базы данных приведен в листинге 6.12.

Листинг 6.12. secretdb.php — применение MySQL для простого механизма аутентификации.

Please Log In This page is secret.

echo » Here it is! «;

echo «I bet you are glad you can see this secret page.»; >

echo «You are not authorized to view this resource.»; >

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

Листинг 6.13. createauthdb.sql —создание базы данных, таблицы и двоих пользователей.

create database auth;

create table auth (

name varchar(10) not null,

pass varchar(30) not null,

primary key (name)

insert into auth values (‘user’, ‘pass’);

insert into auth values

grant select, insert, update, delete

identified by ‘webauth’;

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

РНР-функция crypt() представляет собой однонаправленную криптографическую хэш-функцию. Прототип этой функции таков:

string crypt (string str[, string salt])

Получив на входе строку str, эта функция возвращает псевдослучайную строку. Например, если передать в функцию строку «pass» и аргумент salt равный «хх», то crypt() вернет строку «xxkTlmYjlikoII». Эта строка не может быть дешифрована и превращена обратно в «pass» даже ее создателем, поэтому на первый взгляд строка может и не показаться столь уж полезной. Что делает функцию crypt() полезной, так это то, что результат этой функции детерминирован. При каждом вызове с одними и теми же параметрами str и salt эта функция будет возвращать один и тот же результат.

Вместо РНР-кода, такого как

if( $username == «user» && password == «pass» )

можно воспользоваться таким кодом

if($username= ‘user’ && crypt($password,’хх’) == ‘xxkTlmYjlikoII’)

Нам не требуется знать, как выглядела строка «xxkTlmYjlikoH» перед использованием функции crypt(). Необходимо только знать, совпадает ли введенный пароль тем паролем, для которого применялась функция crypt().

Как уже упоминалось, жесткое кодирование правильных имен и паролей посетителей — плохая идея. Для этого следует организовать отдельный файл или базу данных. Если для хранения данных аутентификации используется база данных MySQL, можно воспользоваться РНР-функцией crypt() или MySQL-функцией PASSWORD(). результат этих функций не совпадает, но они имеют одно предназначение. Обе функции — crypt() и PASSWORD() — получают строку как аргумент и применяют к поденной строке необращаемый алгоритм хэширования.

Чтобы задействовать функцию PASSWORD() в листинге 14.2 запрос SQL следует переписать так:

select count (*) from auth where

Этот запрос посчитает количество строк в таблице auth, в которых значение поля name совпадает с содержимым переменной $name, а поля pass — с результатом функции PASSWORD(), примененной к значению переменной $password. Если мы заставляем посетителей выбирать уникальные имена, результатом запроса может быть 0 или 1.

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

Чтобы самостоятельно создать такую функциональность, потребуется включить части листинга 6.11 в каждую страницу, которую необходимо защитить. При помощи директив auto_prepend_file и auto_append_file требуемый файл можно автоматически вставить в начало (prepend) или в конец (append) каждого файла в указанных каталогах.

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

Можно включить введенную пользователем информацию в каждую гиперссылку на странице. Так как пользователи могут применять пробелы или другие символы, запре­щенные в URL, следует обратиться к функции urlencode(), чтобы безопасно упаковать подобные символы.

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

Решить проблему можно с помощью двух механизмов — базовой HTTP-аутентификации и поддержки сеансов. Базовая аутентификация позволяет решить проблему кэширования, но сервер все равно отправляет пароль Web-браузеру в каждом запросе. Управление сеансами позволяет решить обе проблемы. Сначала рассмотрим базовую HTTP-аутентификацию, а управление сеансами освещается далее.

Базовая аутентификация.К счастью, аутентификация пользователей — это достаточно распространенная задача и существуют возможности аутентификации, встроенные в HTTP-протокол. Сценарии и Web-серверы могут запрашивать аутентификацию у Web-браузера. После этого Web-браузер должен вывести на экран диалоговое окно или что-то подобное и запросить у пользователя необходимую информацию.

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

Описанная возможность HTTP-протокола называется базовой аутентификацией. Ба­овую аутентификацию можно включить средствами РНР или с помощью Web-сервера, Apache и IIS. Далее рассматриваются методы, предполагающие использование РНР.

Базовая аутентификация передает имя пользователя и пароль в виде простого текста и поэтому не особо безопасна. Протокол HTTP 1.1 обладает более безопасным методом, называемым дайджест-аутентификацией (digest authentication). Этот метод использует алгоритм хэширования (как правило, MD5) для маскировки деталей транзакции. Дайджест-аутентификация поддерживается во многих Web-серверах, но не поддерживается в значительном числе браузеров. Дайджест-аутентификация поддерживается в браузере Microsoft Internet Explorer начиная с версии 5.0. Поддержка дайджест-аутентификации включена в Netscape Navigator версию 6.0.

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

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

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

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

Использование базовой аутентификации в РНР.РНР-сценарии, в основном, можно назвать кросс-платформенными, но использование базовой аутентификации базируется на переменных среды, устанавливаемых сервером. Сценарий HTTP-аутентификации должен определять тип сервера и вести себя соответствующим образом в зависимости от того, выполняется ли он как модуль Apache на сервере Apache или как ISAPI-модуль на сервере IIS. Показанный в листинге 6.14 сценарий будет выполняться на обоих серверах.

Листинг 6.14. http.php — включение базовой HTTP-аутентификации средствами РНР.

echo «You are not authorized to view this resource.»; >

// посетитель предоставил правильную информацию

Here it is! «;

I bet you are glad you can see this secret page.»;

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

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

Поскольку для аутентификации применяются встроенные возможности браузеров, последние демонстрируют некоторую осторожность в обработке неудачных попыток аутентификации. Internet Explorer дает пользователю три попытки аутентификации, и если все они проходят неудачно, выводится сообщение об отказе в доступе. Netscape Navigator предоставляет неограниченное число попыток, но между попытками выводит диалоговое окно с запросом о повторе «Authentication Failed. Retry?». Netscape отображает сообщение об отказе в доступе, только когда пользователь щелкает на кнопке Cancel.

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

Дата добавления: 2015-11-04 ; просмотров: 918 ; ЗАКАЗАТЬ НАПИСАНИЕ РАБОТЫ

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL