Logowanie uwierzytelniania HTTP przez PHP

Jaki jest poprawny sposób wylogowania się z chronionego folderu uwierzytelniania HTTP?

Istnieją obejścia, które mogą to osiągnąć, ale są potencjalnie niebezpieczne, ponieważ mogą być wadliwe lub nie działają w pewnych sytuacjach / przeglądarkach. Dlatego szukam poprawnego i czystego rozwiązania.

Author: bignose, 2009-01-16

17 answers

Mu. nie istnieje żadna poprawna droga , nawet taka, która jest spójna w różnych przeglądarkach.

Jest to problem, który wynika ze specyfikacji HTTP (sekcja 15.6):

Istniejące klienty HTTP i agenci użytkowników zazwyczaj zachowują uwierzytelnianie informacje na czas nieokreślony. HTTP / 1.1. nie zapewnia metody na serwer do kierowania klientów do odrzucenia tych poświadczeń pamięci podręcznej.

Z drugiej strony sekcja 10.4.2 says:

Jeśli wniosek zawierał już poświadczenia autoryzacji, to 401 odpowiedź wskazuje, że odmówiono autoryzacji dla tych poświadczenia. Jeżeli odpowiedź 401 Zawiera to samo wyzwanie co uprzedniej odpowiedzi, a agent użytkownika już próbował uwierzytelniania co najmniej raz, wtedy Użytkownik powinien przedstawić podmiot, który został podany w odpowiedzi, ponieważ podmiot ten może zawierać istotne informacje diagnostyczne.

Innymi słowy, Być może będziesz w stanie ponownie pokazać okno logowania (jak mówi @Karsten), ale przeglądarka nie musi spełniać TWOJEJ prośby - więc nie polegaj zbytnio na tej (mis)funkcji.

 102
Author: Piskvor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:30

Metoda, która działa dobrze w Safari. Działa również w Firefoksie i operze, ale z ostrzeżeniem.

Location: http://[email protected]/

To polecenie mówi przeglądarce, aby otworzyła adres URL z nową nazwą użytkownika, nadpisując poprzednią.

 57
Author: Kornel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-21 21:44:52

Prosta odpowiedź jest taka, że nie można niezawodnie wylogować się z uwierzytelniania http.

Długa odpowiedź:
Http-auth (podobnie jak reszta specyfikacji HTTP) ma być bezstanowe. Tak więc bycie "zalogowanym" lub "wylogowanym" nie jest tak naprawdę pojęciem, które ma sens. Lepszym sposobem, aby to zobaczyć, jest poproszenie, dla każdego żądania HTTP (i pamiętaj, że ładowanie strony to zwykle wiele żądań), "czy możesz zrobić to, o co prosisz?". Serwer widzi każde żądanie jako nowe i niezwiązane z jakimkolwiek poprzednim prośby.

Przeglądarki zdecydowały się zapamiętać dane uwierzytelniające, które podajesz im w pierwszym 401, i ponownie wysłać je bez wyraźnej zgody użytkownika na kolejne żądania. Jest to próba nadania użytkownikowi oczekiwanego modelu "zalogowanego/wylogowanego", ale to tylko kludge. To przeglądarka symuluje tę trwałość stanu. Serwer WWW jest tego zupełnie nieświadomy.

Więc" wylogowanie się", w kontekście http-auth jest wyłącznie symulacją dostarczone przez przeglądarkę, a więc poza władzą serwera.

Tak, są kludges. Ale łamią spokój (jeśli to ma dla Ciebie wartość) i są zawodni.

Jeśli absolutnie potrzebujesz modelu logowania/wylogowania do uwierzytelniania witryny, najlepszym rozwiązaniem jest śledzący plik cookie, z trwałością stanu przechowywanego na serwerze w jakiś sposób (mysql, SQLite, flatfile itp.). Będzie to wymagało oceny wszystkich żądań, na przykład za pomocą PHP.

 43
Author: Jonathan Hanson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-11 13:37:36

Obejście

Możesz to zrobić używając 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>

To co jest zrobione powyżej to:

  • Dla IE - wystarczy wyczyścić auth cache i przekierować gdzieś

  • Dla innych przeglądarek - Wyślij zapytanie XMLHttpRequest za kulisami z nazwą logowania i hasłem. Musimy wysłać go do jakiejś ścieżki, która zwróci 200 OK do tego żądania (tzn. nie powinna wymagać uwierzytelniania HTTP).

Zastąp '/where/to/redirect' przez jakaś ścieżka do przekierowania po wylogowaniu i zastąpienia '/path/that/will/return/200/OK' jakąś ścieżką na twojej stronie, która zwróci 200 OK.

 24
Author: Anton Mochalin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-12 20:12:53

Workaround (nie czysty, miły (lub nawet działa! Zobacz komentarze) rozwiązanie):

Wyłącz jego dane uwierzytelniające jeden raz.

Możesz przenieść logikę uwierzytelniania HTTP do PHP, wysyłając odpowiednie nagłówki (jeśli nie jesteś zalogowany):

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

I parsowanie wejścia za pomocą:

$_SERVER['PHP_AUTH_USER'] // httpauth-user
$_SERVER['PHP_AUTH_PW']   // httpauth-password
Więc wyłączenie jego uprawnień powinno być banalne.
 13
Author: Karsten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-18 11:58:55

Wyloguj się z HTTP Basic Auth w dwóch krokach

Załóżmy, że mam HTTP basic auth realm o nazwie "Password protected", a Bob jest zalogowany. Aby się wylogować składam 2 żądania AJAX:

  1. skrypt dostępu / logout_step1. Dodaje losowego użytkownika tymczasowego do .htusers i odpowiada swoim loginem i hasłem.
  2. skrypt dostępu / logout_step2 uwierzytelniony tymczasowym loginem i hasłem użytkownika. Skrypt usuwa tymczasowego użytkownika i dodaje ten nagłówek na odpowiedź: WWW-Authenticate: Basic realm="Password protected"
W tym momencie browser zapomniał danych Boba.
 7
Author: Vlad GURDIGA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-23 21:04:29

Moje rozwiązanie problemu jest następujące. Możesz znaleźć funkcję http_digest_parse , $realm i $users w drugim przykładzie tej strony: 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,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-01 23:38:59

Zazwyczaj, gdy przeglądarka poprosi użytkownika o poświadczenia i dostarczy je do konkretnej witryny internetowej, będzie to robić bez dalszego pytania. W przeciwieństwie do różnych sposobów usuwania plików cookie po stronie klienta, nie znam podobnego sposobu, aby poprosić przeglądarkę o zapomnienie dostarczonych danych uwierzytelniających.

 4
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 08:01:49

Trac-domyślnie-używa również uwierzytelniania HTTP. Wylogowanie nie działa i nie można go naprawić:

  • jest to problem z samym schematem uwierzytelniania HTTP i nie możemy nic zrobić w Trac, aby naprawić go poprawnie.
  • obecnie nie istnieje obejście (JavaScript lub inne), które działa ze wszystkimi głównymi przeglądarkami.

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

Wygląda na to, że nie ma działa odpowiedź na pytanie, że problem został zgłoszony siedem lat temu i to ma sens: HTTP jest bezpaństwowy. Albo żądanie jest wykonywane z poświadczeniami uwierzytelniania, albo nie. Ale to kwestia wysłania żądania przez Klienta, a nie serwera, który je otrzyma. Serwer może tylko powiedzieć, czy żądanie URI wymaga autoryzacji, czy nie.

 2
Author: hakre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-06 18:05:28

Musiałem zresetować .autoryzacja htaccess więc użyłem tego:

<?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;
}
?>

Znalazłem go tutaj : http://php.net/manual/en/features.http-auth.php

/ Align = "left" /

Na tej stronie znajduje się wiele rozwiązań, a nawet na dole notuje: Lynx, nie wyczyszcza auth jak inne przeglądarki;)

Przetestowałem go na moich zainstalowanych przeglądarkach i po zamknięciu każda przeglądarka wydaje się konsekwentnie wymagać reauth na reentry.

 2
Author: Dooley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-07 07:00:52

To może nie jest rozwiązanie, którego szukano, ale ja rozwiązałem to w ten sposób. mam 2 skrypty do procesu wylogowania.

Wyloguj się.php

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

Log.php

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

W ten sposób nie dostaję ostrzeżenia i moja sesja jest zakończona

 2
Author: Kevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-02 19:16:22

AFAIK, nie ma czystego sposobu na zaimplementowanie funkcji "wyloguj" przy użyciu uwierzytelniania htaccess (tj. opartego na HTTP).

Dzieje się tak dlatego, że takie uwierzytelnianie wykorzystuje kod błędu HTTP '401', aby poinformować przeglądarkę, że wymagane są poświadczenia, w którym to momencie przeglądarka prosi użytkownika o szczegóły. Od tego momentu, aż przeglądarka zostanie zamknięta, zawsze będzie wysyłać poświadczenia bez dalszego monitowania.

 1
Author: Alnitak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-16 08:03:37

Najlepsze rozwiązanie jakie dotychczas znalazłem to (jest to rodzaj pseudo-kodu, $isLoggedIn to pseudo zmienna dla HTTP auth):

W czasie "wylogowania" po prostu przechowuj pewne informacje o sesji informujące, że użytkownik jest rzeczywiście wylogowany.

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

W miejscu gdzie sprawdzam autentyczność rozwijam warunek:

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

Sesja jest w pewnym stopniu powiązana ze stanem uwierzytelniania http, więc użytkownik pozostaje wylogowany tak długo, jak długo utrzymuje otwartą przeglądarkę i tak długo, jak uwierzytelnianie http trwa w przeglądarce.

 1
Author: Josef Sábl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-30 09:14:19

Może nie o to mi chodzi.

Najbardziej niezawodnym sposobem, jaki znalazłem, aby zakończyć Uwierzytelnianie HTTP, jest zamknięcie przeglądarki i wszystkich okien przeglądarki. Możesz zamknąć okno przeglądarki za pomocą Javascript, ale nie sądzę, że możesz zamknąć wszystkie okna przeglądarki.

 1
Author: Toby Allen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-23 23:24:36

Podczas gdy inni mają rację mówiąc, że niemożliwe jest wylogowanie się z podstawowego uwierzytelniania http, istnieją sposoby implementacji uwierzytelniania, które zachowują się podobnie. Jednym z oczywistych appeoach jest użycie auth_memcookie . Jeśli naprawdę chcesz zaimplementować podstawowe uwierzytelnianie HTTP (tzn. użyj okien dialogowych przeglądarki do logowania się bardziej niż formularz HTTP )za pomocą tego-po prostu ustaw uwierzytelnianie na oddzielną.zabezpieczony katalog htaccess zawierający skrypt PHP, który przekierowuje z powrotem, gdzie te użytkownik przyszedł po utworzeniu sesji memcache.

 0
Author: symcbean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-01 13:03:57

Jest tu wiele świetnych - złożonych - odpowiedzi. W moim konkretnym przypadku znalazłem czystą i prostą poprawkę dla wylogowania. Muszę jeszcze przetestować w Edge. Na mojej stronie, na której się zalogowałem, umieściłem link do wylogowania podobny do tego:

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

I w głowie tego wylogowania.strona html (która jest również chroniona przez .htaccess) mam odświeżanie strony podobne do tego:

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

Gdzie można zostawić słowa "Wyloguj" w miejscu, aby wyczyścić nazwę użytkownika i hasło buforowane dla miejscu.

Przyznam, że jeśli wiele stron musiało być zalogowanych bezpośrednio od początku, każdy z tych punktów wejścia wymagałby własnego odpowiedniego wylogowania.strona html. W przeciwnym razie możesz scentralizować wylogowanie, wprowadzając dodatkowy krok strażnika przed rzeczywistym monitem logowania, wymagający wprowadzenia frazy, aby dotrzeć do miejsca logowania.

 0
Author: johnwayne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-18 08:26:36

Jedynym skutecznym sposobem na wymazanie poświadczeń PHP_AUTH_DIGEST lub PHP_AUTH_USER I PHP_AUTH_PW jest wywołanie nagłówka HTTP/1.1 401 Unauthorized.

function clear_admin_access(){
    header('HTTP/1.1 401 Unauthorized');
    die('Admin access turned off');
}
 -1
Author: CIRCLE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-07 15:59:04