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


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

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

Author: bignose, 2009-01-16

17 answers

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

Эта проблема возникает из спецификации HTTP (раздел 15.6):

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

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

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

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

 102
Author: Piskvor, 2017-05-23 12:10:30

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

Location: http://[email protected]/

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

 57
Author: Kornel, 2012-03-21 21:44:52

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

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

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

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

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

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

 43
Author: Jonathan Hanson, 2010-04-11 13:37:36

Обходной путь

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

<html><head>
<script type="text/javascript">
function logout() {
    var xmlhttp;
    if (window.XMLHttpRequest) {
          xmlhttp = new XMLHttpRequest();
    }
    // code for IE
    else if (window.ActiveXObject) {
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    if (window.ActiveXObject) {
      // IE clear HTTP Authentication
      document.execCommand("ClearAuthenticationCache");
      window.location.href='/where/to/redirect';
    } else {
        xmlhttp.open("GET", '/path/that/will/return/200/OK', true, "logout", "logout");
        xmlhttp.send("");
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4) {window.location.href='/where/to/redirect';}
        }


    }


    return false;
}
</script>
</head>
<body>
<a href="#" onclick="logout();">Log out</a>
</body>
</html>

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

  • Для IE - просто очистите кэш аутентификации и перенаправьте куда-нибудь

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

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

 24
Author: Anton Mochalin, 2012-10-12 20:12:53

Обходной путь (не чистый, приятный (или даже работающий! смотрите комментарии) решение):

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

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

Header('WWW-Authenticate: Basic realm="protected area"');
Header('HTTP/1.0 401 Unauthorized');

И анализ входных данных с помощью:

$_SERVER['PHP_AUTH_USER'] // httpauth-user
$_SERVER['PHP_AUTH_PW']   // httpauth-password

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

 13
Author: Karsten, 2012-01-18 11:58:55

Выход из базовой аутентификации HTTP в два этапа

Допустим, у меня есть базовая область аутентификации HTTP с именем "Защищен паролем", и Боб вошел в систему. Чтобы выйти из системы, я делаю 2 запроса AJAX:

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

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

 7
Author: Vlad GURDIGA, 2012-08-23 21:04:29

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

session_start();

function LogOut() {
  session_destroy();
  session_unset($_SESSION['session_id']);
  session_unset($_SESSION['logged']);

  header("Location: /", TRUE, 301);   
}

function Login(){

  global $realm;

  if (empty($_SESSION['session_id'])) {
    session_regenerate_id();
    $_SESSION['session_id'] = session_id();
  }

  if (!IsAuthenticated()) {  
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
   '",qop="auth",nonce="'.$_SESSION['session_id'].'",opaque="'.md5($realm).'"');
    $_SESSION['logged'] = False;
    die('Access denied.');
  }
  $_SESSION['logged'] = True;  
}

function IsAuthenticated(){
  global $realm;
  global $users;


  if  (empty($_SERVER['PHP_AUTH_DIGEST']))
      return False;

  // check PHP_AUTH_DIGEST
  if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
     !isset($users[$data['username']]))
     return False;// invalid username


  $A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
  $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);

  // Give session id instead of data['nonce']
  $valid_response =   md5($A1.':'.$_SESSION['session_id'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

  if ($data['response'] != $valid_response)
    return False;

  return True;
}
 6
Author: Pie86, 2014-01-01 23:38:59

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

 4
Author: Greg Hewgill, 2009-01-16 08:01:49

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

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

От: http://trac.edgewall.org/ticket/791#comment:103

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

 2
Author: hakre, 2011-08-06 18:05:28

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

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
}
?>

Нашел его здесь : http://php.net/manual/en/features.http-auth.php

Пойди разберись.

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

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

 2
Author: Dooley, 2011-12-07 07:00:52

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

Logout.php

<?php
header("Location: http://[email protected]/log.php");
?>

Log.php

<?php
header("location: https://google.com");
?>

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

 2
Author: Kevin, 2015-03-02 19:16:22

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

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

 1
Author: Alnitak, 2009-01-16 08:03:37

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

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

function logout()
{
  //$isLoggedIn = false; //This does not work (point of this question)
  $_SESSION['logout'] = true;
}

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

function isLoggedIn()
{
  return $isLoggedIn && !$_SESSION['logout'];
}

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

 1
Author: Josef Sábl, 2009-09-30 09:14:19

Может быть, я упускаю главное.

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

 1
Author: Toby Allen, 2012-08-23 23:24:36

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

 0
Author: symcbean, 2011-08-01 13:03:57

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

<a href="https://MyDomainHere.net/logout.html">logout</a>

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

<meta http-equiv="Refresh" content="0; url=https://logout:[email protected]/" />

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

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

 0
Author: johnwayne, 2017-10-18 08:26:36

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

function clear_admin_access(){
    header('HTTP/1.1 401 Unauthorized');
    die('Admin access turned off');
}
 -1
Author: CIRCLE, 2015-06-07 15:59:04