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



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



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

1743   17  

17 ответов:

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

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

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

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

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

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

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

Location: http://[email protected]/

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

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

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

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

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

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

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

решение

вы можете сделать это с помощью 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 за кулисами с именем входа и паролем "logout". Нам нужно отправить его на какой-то путь, который вернет 200 OK к этому запросу (т. е. он не должен требовать Проверка подлинности по протоколу HTTP).

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

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

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

вы можете переместить логику аутентификации 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

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

выход из HTTP Basic Auth в два этапа

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

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

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

мое решение проблемы заключается в следующем. Вы можете найти функцию 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;
}

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

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

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

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

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

Мне нужно сбросить .авторизация 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, не очищает auth, как и другие браузеры;)

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

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

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

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

log.php

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

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

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

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

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

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

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

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

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

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

может быть, я упускаю суть.

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

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

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

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

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

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

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

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

единственный действенный способ, который я нашел, чтобы уничтожить 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');
}

Comments

    Ничего не найдено.