Jak wylogować użytkownika ze strony internetowej przy użyciu uwierzytelnienia BASIC?


279

Czy można wylogować użytkownika ze strony internetowej, jeśli korzysta on z podstawowego uwierzytelnienia?

Sesja zabijania nie wystarczy, ponieważ po uwierzytelnieniu użytkownika każde żądanie zawiera dane logowania, więc użytkownik jest automatycznie logowany przy następnym dostępie do witryny przy użyciu tych samych danych logowania.

Jak dotąd jedynym rozwiązaniem jest zamknięcie przeglądarki, ale z punktu widzenia użyteczności jest to nie do przyjęcia.


1
Po prostu ciekawy. Dlaczego chcesz to zrobić?
DOK

17
Aby móc zalogować się jako inny użytkownik.
Marko

16
@DOK - To standardowa funkcja hakowania społecznościowego: użytkownicy powinni mieć możliwość wylogowania się, pozostawiając otwartą przeglądarkę. Załóżmy, że jeden z Twoich użytkowników uzyskuje dostęp do witryny na komputerze publicznym? Muszą się wylogować, aby następny użytkownik nie mógł uzyskać dostępu do witryny jako oni.
Keith,

@DOK Istnieje również problem polegający na tym, że uniemożliwia użytkownikowi wylogowanie się z witryny. Serwer może wyczyścić plik cookie autoryzacji, a nawet plik cookie sesji. Ale gdy przeglądarka przejdzie do ładowania /strony, zostaną automatycznie ponownie zalogowani.
Ian Boyd

Używam metody, która wysyła fałszywe żądanie wylogowania, ale blokuje użytkownika w kliencie, ponieważ istnieje ostre ograniczenie, że 3 razy logowanie nie powiodło się w AD. Dlatego sugeruj ostrożność przy użyciu tej metody (wysyłanie fałszywego żądania).
Qianchao Pan

Odpowiedzi:


170

Podstawowe uwierzytelnianie nie zostało zaprojektowane do zarządzania wylogowaniem. Możesz to zrobić, ale nie całkowicie automatycznie.

Musisz tylko kliknąć link wylogowania i wysłać odpowiedź „401 Nieautoryzowany”, korzystając z tej samej dziedziny i na tym samym poziomie folderu URL, co zwykły numer 401 wysyłany z prośbą o zalogowanie.

Muszą zostać poproszeni o podanie nieprawidłowych danych uwierzytelniających, np. pusta nazwa użytkownika i hasło, a w odpowiedzi odsyłasz stronę „Wylogowanie się powiodło”. Błędne / puste poświadczenia zastąpią poprzednie poprawne poświadczenia.

Krótko mówiąc, skrypt wylogowania odwraca logikę skryptu logowania, zwracając stronę sukcesu tylko wtedy, gdy użytkownik nie przejdzie odpowiednich poświadczeń.

Pytanie brzmi, czy nieco dziwne okno hasła „nie wprowadzaj hasła” spotka się z akceptacją użytkownika. Menedżerowie haseł, którzy próbują automatycznie uzupełnić hasło, również mogą przeszkodzić tutaj.

Edytuj, aby dodać w odpowiedzi na komentarz: ponowne zalogowanie jest nieco innym problemem (chyba że potrzebujesz oczywiście dwuetapowego wylogowania / logowania). Musisz odrzucić (401) pierwszą próbę dostępu do linku ponownego logowania, niż zaakceptować drugą (która prawdopodobnie ma inną nazwę użytkownika / hasło). Można to zrobić na kilka sposobów. Jednym z nich byłoby dołączenie bieżącej nazwy użytkownika do linku wylogowania (np. / Relogin? Nazwa użytkownika) i odrzucenie, gdy poświadczenia są zgodne z nazwą użytkownika.


2
Spróbuję tego podejścia. Celem wylogowania (w tym przypadku) jest umożliwienie użytkownikowi zalogowania się jako inny użytkownik, więc jest to całkowicie akceptowalne rozwiązanie. Jeśli chodzi o hasło autouzupełniania, od użytkownika zależy, czy będzie go używał, czy nie. Dzięki
Marko

Czy to wciąż jedyny sposób? Zrobiłem implementację ASP.Net MVC i jQuery, która działa, ale nadal nie jestem z tego zadowolony: stackoverflow.com/questions/6277919
Keith

@Keith: Wciąż tylko to i odpowiedź systemPAUSE (która nie działa we wszystkich przeglądarkach, ale jest płynniejsza niż ręczne podejście, gdy działa).
bobince

16
W3C jest tak aktywny w specyfikacji HTML. Ale specyfikacja HTTP słabnie. W3C powinien był rozwiązać ten problem około dwie dekady temu. Wraz ze wzrostem korzystania z usług REST potrzebna jest solidna natywna metoda uwierzytelniania.
Dojo

9
Nie działa to poprawnie w przeglądarce Chrome 46 na localhost. Wygląda na to, że Chrome zachowuje zarówno stare (prawidłowe) hasło, jak i nowe hasło, które określisz. Po przejściu na stronę wylogowania Chrome poprawnie używa nowego hasła, AŻ DO SPOTKAŃ IT 401 NIEAUTORYZOWANYCH NA STRONIE NA TWOJEJ STRONIE. Po pierwszym 401 Chrome powraca do starego (poprawnego) hasła. Tak naprawdę to tak naprawdę nie usunęło hasła.
vancan1ty

196

Dodatek do odpowiedzi bobince ...

Dzięki Ajax możesz połączyć link / przycisk „Wyloguj” z funkcją Javascript. Niech ta funkcja wyśle ​​XMLHttpRequest z niepoprawną nazwą użytkownika i hasłem. To powinno odzyskać 401. Następnie ustaw document.location z powrotem na stronę przed logowaniem. W ten sposób użytkownik nigdy nie zobaczy dodatkowego okna logowania podczas wylogowywania, ani nie będzie musiał pamiętać o wprowadzeniu złych danych logowania.


12
Dobry hack, ręczne wprowadzanie złych danych uwierzytelniających użytkownika jest prawdopodobnie nie do przyjęcia dla większości aplikacji internetowych.
BillMan

1
Upewnij się tylko, że XMLHttpRequest nie jest ustawiony jako asynchroniczny, ponieważ możesz przekierować, że nastąpi przekierowanie przed zakończeniem żądania wylogowania.
davidjb

5
Możesz użyć tej samej sztuczki również do logowania. W ten sposób można dostosować okno dialogowe logowania bez konieczności zmiany metody uwierzytelniania serwera. W tym artykule podano kilka dobrych pomysłów: http://www.peej.co.uk/articles/http-auth-with-html-forms.html
Stijn de Witt

1
@davidjb Ponieważ żądania synchroniczne są obecnie uznawane za przestarzałe, alternatywnym rozwiązaniem może być przekierowanie użytkownika w wywołaniu zwrotnym żądania asynchronicznego.
Hayden Schiff,

1
David: chrome pozwala teraz na XHR i mogę potwierdzić, że nadal działa na kanale chrome. bugs.chromium.org/p/chromium/issues/detail?id=435547
CpnCrunch

192

Poproś użytkownika o kliknięcie linku do https: // log: out@example.com/ . Spowoduje to zastąpienie istniejących poświadczeń nieprawidłowymi; wylogowanie ich.


19
Dlaczego ten nie ma więcej głosów pozytywnych? Wydaje mi się to prostym i działającym rozwiązaniem. Czy są jakieś znane problemy z tym podejściem?
amoebe

35
Nie działałoby to już w Chrome, który ze względów bezpieczeństwa ignoruje poświadczenia w adresie URL.
Thom

5
To zadziałało dla mnie :) Korzystam z wersji Chrome 32.0.1700.102
abottoni

6
problem: przy użyciu wersji 39.0 chrome, kiedy klikam link wylogowania za pomocą tej metody, Chrome zapamiętuje złe dane logowania i wyświetla monit o nowe dane logowania przy każdym ładowaniu strony, dopóki nie przejdę do example.com bez żadnych danych logowania, aby wyczyść pamięć chrome.
Scott

4
Cześć, nie mogę go używać do https w Chrome.
thienkhoi tran

67

Możesz to zrobić całkowicie w JavaScript:

IE ma (przez długi czas) standardowy interfejs API do czyszczenia pamięci podręcznej podstawowego uwierzytelniania:

document.execCommand("ClearAuthenticationCache")

Powinien zwrócić wartość true, gdy działa. Zwraca wartość false, niezdefiniowany lub wysadza się w innych przeglądarkach.

Nowe przeglądarki (od grudnia 2012 r .: Chrome, FireFox, Safari) działają „magicznie”. Jeśli zobaczą udane podstawowe żądanie autoryzacji z dowolną inną fałszywą nazwą użytkownika (powiedzmy logout), usuwają pamięć podręczną poświadczeń i ewentualnie ustawiają ją dla tej nowej fałszywej nazwy użytkownika, którą musisz upewnić się, że nie jest prawidłową nazwą użytkownika do przeglądania treści.

Podstawowym przykładem tego jest:

var p = window.location.protocol + '//'
// current location must return 200 OK for this GET
window.location = window.location.href.replace(p, p + 'logout:password@')

„Asynchronicznym” sposobem wykonania powyższego jest wykonanie wywołania AJAX przy użyciu logoutnazwy użytkownika. Przykład:

(function(safeLocation){
    var outcome, u, m = "You should be logged out now.";
    // IE has a simple solution for it - API:
    try { outcome = document.execCommand("ClearAuthenticationCache") }catch(e){}
    // Other browsers need a larger solution - AJAX call with special user name - 'logout'.
    if (!outcome) {
        // Let's create an xmlhttp object
        outcome = (function(x){
            if (x) {
                // the reason we use "random" value for password is 
                // that browsers cache requests. changing
                // password effectively behaves like cache-busing.
                x.open("HEAD", safeLocation || location.href, true, "logout", (new Date()).getTime().toString())
                x.send("")
                // x.abort()
                return 1 // this is **speculative** "We are done." 
            } else {
                return
            }
        })(window.XMLHttpRequest ? new window.XMLHttpRequest() : ( window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : u ))
    }
    if (!outcome) {
        m = "Your browser is too old or too weird to support log out functionality. Close all windows and restart the browser."
    }
    alert(m)
    // return !!outcome
})(/*if present URI does not return 200 OK for GET, set some other 200 OK location here*/)

Możesz też zrobić z niego bookmarklet:

javascript:(function(c){var a,b="You should be logged out now.";try{a=document.execCommand("ClearAuthenticationCache")}catch(d){}a||((a=window.XMLHttpRequest?new window.XMLHttpRequest:window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):void 0)?(a.open("HEAD",c||location.href,!0,"logout",(new Date).getTime().toString()),a.send(""),a=1):a=void 0);a||(b="Your browser is too old or too weird to support log out functionality. Close all windows and restart the browser.");alert(b)})(/*pass safeLocation here if you need*/);


1
Czy wymaga to specjalnej obsługi logoutnazwy użytkownika i / lub adresu URL wylogowania po stronie serwera ?
ulidtko

1
@ulidtko Nie, nie powinno - cała obsługa odbywa się po stronie klienta. Jedyną sytuacją, która wymagałaby specjalnej obsługi, jest sytuacja, w której wywoływany użytkownik logoutistnieje i ma wygenerowane hasło. W tym prawie niemożliwie rzadkim przypadku zmień identyfikator użytkownika na taki, który nie będzie istniał w twoim systemie.
davidjb

2
Użyłem dziś bookmarkletu powyżej i działam dobrze.
David Gleba

Użyłem tego i działało to dla Chrome i FF. Musiałem tylko zrobić dodatkowe „GET” na mojej stronie logout.php, aby wyczyścić $ _SESSION.
miejski

2
Bookmarklet działa również na Edge. Po prostu użyj z<a href='javascript:......need*/);'>Logout</a>
Eric

21

Potwierdzono działanie następującej funkcji dla Firefox 40, Chrome 44, Opera 31 i IE 11.
Bowser służy do wykrywania przeglądarki, jQuery jest również używany.

- secUrl to adres URL obszaru chronionego hasłem, z którego należy się wylogować.
- redirUrl to adres URL do obszaru niechronionego hasłem (strona udanego wylogowania).
- możesz zwiększyć czas przekierowania (obecnie 200 ms).

function logout(secUrl, redirUrl) {
    if (bowser.msie) {
        document.execCommand('ClearAuthenticationCache', 'false');
    } else if (bowser.gecko) {
        $.ajax({
            async: false,
            url: secUrl,
            type: 'GET',
            username: 'logout'
        });
    } else if (bowser.webkit) {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET", secUrl, true);
        xmlhttp.setRequestHeader("Authorization", "Basic logout");
        xmlhttp.send();
    } else {
        alert("Logging out automatically is unsupported for " + bowser.name
            + "\nYou must close the browser to log out.");
    }
    setTimeout(function () {
        window.location.href = redirUrl;
    }, 200);
}


to jest najbardziej wyczerpująca odpowiedź
belidzs

Czy jest jakiś powód, dla którego $.ajaxwariant jest synchroniczny ( async: false), a xmlhttpwariant jest asynchroniczny ( truein open())?
Bowi,

1
Chrome używa teraz silnika renderowania Blink, więc musisz się zmienić (bowser.gecko)na (bowser.gecko || bowser.blink).
Bowi

1
Dlaczego używa się Gecko / Blink $.ajaxi Webkit new XMLHttpRequest? Czy gecko / blink nie powinien być w stanie zrobić, XMLHttpRequesta webkit $.ajaxtakże? Jestem zmieszany.
RemyNL

11

Oto bardzo prosty przykład Javascript za pomocą jQuery:

function logout(to_url) {
    var out = window.location.href.replace(/:\/\//, '://log:out@');

    jQuery.get(out).error(function() {
        window.location = to_url;
    });
}

Ten użytkownik dziennika bez pokazując mu przeglądarkę dziennika w oknie ponownie, a następnie przekierować go do wylogowany stronę


1
window.location = window.location.href.replace (/: \ / \ //, ': // log: out @');
sebhaase

10

Nie jest to bezpośrednio możliwe w przypadku podstawowego uwierzytelnienia.

W specyfikacji HTTP nie ma mechanizmu informującego przeglądarkę, aby przestała wysyłać poświadczenia, które użytkownik już przedstawił.

Istnieją „włamania” (patrz inne odpowiedzi), zwykle polegające na użyciu XMLHttpRequest w celu wysłania żądania HTTP z niepoprawnymi danymi uwierzytelniającymi w celu zastąpienia oryginalnie podanych.


12
W teorii. Praktyka dowodzi inaczej, jak wynika z innych odpowiedzi.
Stijn de Witt

2
Jak widać z innych odpowiedzi, nie w sposób niezawodny, spójny i bezpieczny w razie awarii!
jplandrain

5

Działa to dla IE / Netscape / Chrome:

      function ClearAuthentication(LogOffPage) 
  {
     var IsInternetExplorer = false;    

     try
     {
         var agt=navigator.userAgent.toLowerCase();
         if (agt.indexOf("msie") != -1) { IsInternetExplorer = true; }
     }
     catch(e)
     {
         IsInternetExplorer = false;    
     };

     if (IsInternetExplorer) 
     {
        // Logoff Internet Explorer
        document.execCommand("ClearAuthenticationCache");
        window.location = LogOffPage;
     }
     else 
     {
        // Logoff every other browsers
    $.ajax({
         username: 'unknown',
         password: 'WrongPassword',
             url: './cgi-bin/PrimoCgi',
         type: 'GET',
         beforeSend: function(xhr)
                 {
            xhr.setRequestHeader("Authorization", "Basic AAAAAAAAAAAAAAAAAAA=");
         },

                 error: function(err)
                 {
                    window.location = LogOffPage;
             }
    });
     }
  }


  $(document).ready(function () 
  {
      $('#Btn1').click(function () 
      {
         // Call Clear Authentication 
         ClearAuthentication("force_logout.html"); 
      });
  });          

5

To jest właściwie całkiem proste.

Wystarczy odwiedzić stronę w przeglądarce i użyć nieprawidłowych danych logowania: http: // nazwa użytkownika: hasło@twojadomena.com

To powinno „wylogować”.


1
Ale użytkownik musi być PRAWDZIWYM użytkownikiem, w przeciwnym razie dostaję komunikat „401 Nieautoryzowany”, ale za pomocą przycisku WSTECZ mogę kontynuować pracę jako wcześniej zalogowany użytkownik. Testowane na serwerze internetowym Abyss X1 (2.11.1)
2956477,

1
Duplikat odpowiedzi (patrz powyżej Matthew Welborn).
Skippy le Grand Gourou,

3

Wystarczy przekierować użytkownika na adres URL wylogowania i zwrócić 401 Unauthorizedbłąd. Na stronie błędu (która musi być dostępna bez podstawowego uwierzytelnienia) musisz podać pełny link do swojej strony głównej (w tym schemat i nazwę hosta). Użytkownik kliknie ten link, a przeglądarka ponownie poprosi o poświadczenia.

Przykład dla Nginx:

location /logout {
    return 401;
}

error_page 401 /errors/401.html;

location /errors {
    auth_basic off;
    ssi        on;
    ssi_types  text/html;
    alias /home/user/errors;
}

Strona błędu /home/user/errors/401.html:

<!DOCTYPE html>
<p>You're not authorised. <a href="<!--# echo var="scheme" -->://<!--# echo var="host" -->/">Login</a>.</p>

Chciałbym dodatkowo zalecamy użycie http_hostw 401.htmlzamiast po prostu host, jako dawny dodaje również numer portu (w przypadku jest używany niestandardowy port)
Emil Koutanov

2
function logout() {
  var userAgent = navigator.userAgent.toLowerCase();

  if (userAgent.indexOf("msie") != -1) {
    document.execCommand("ClearAuthenticationCache", false);
  }

  xhr_objectCarte = null;

  if(window.XMLHttpRequest)
    xhr_object = new XMLHttpRequest();
  else if(window.ActiveXObject)
    xhr_object = new ActiveXObject("Microsoft.XMLHTTP");
  else
    alert ("Your browser doesn't support XMLHTTPREQUEST");

  xhr_object.open ('GET', 'http://yourserver.com/rep/index.php', false, 'username', 'password');
  xhr_object.send ("");
  xhr_object = null;

  document.location = 'http://yourserver.com'; 
  return false;
}

2
 function logout(url){
    var str = url.replace("http://", "http://" + new Date().getTime() + "@");
    var xmlhttp;
    if (window.XMLHttpRequest) xmlhttp=new XMLHttpRequest();
    else xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState==4) location.reload();
    }
    xmlhttp.open("GET",str,true);
    xmlhttp.setRequestHeader("Authorization","Basic xxxxxxxxxx")
    xmlhttp.send();
    return false;
}

2

Na podstawie tego, co przeczytałem powyżej, otrzymałem proste rozwiązanie, które działa w dowolnej przeglądarce:

1) na stronie wylogowania wywołujesz ajax do swojego zaplecza logowania. Twój zaplecze logowania musi zaakceptować użytkownika wylogowania. Po zaakceptowaniu zaplecza przeglądarka wyczyści bieżącego użytkownika i przyjmie użytkownika „wylogowania”.

$.ajax({
    async: false,
    url: 'http://your_login_backend',
    type: 'GET',
    username: 'logout'
});      

setTimeout(function () {
    window.location.href = 'http://normal_index';
}, 200);

2) Teraz, gdy użytkownik powróci do normalnego pliku indeksu, spróbuje automatycznie wejść do systemu z użytkownikiem „wyloguj się”, po raz drugi musisz go zablokować, odpowiadając 401, aby wywołać okno dialogowe logowania / hasła.

3) Można to zrobić na wiele sposobów, utworzyłem dwa zaplecza logowania, jeden akceptujący użytkownika wylogowania, a drugi nie. Moja normalna strona logowania używa strony, która nie akceptuje, moja strona wylogowania używa strony, która ją akceptuje.


2

Właśnie przetestowałem następujące elementy w Chrome (79), Firefox (71) i Edge (44) i działa dobrze. Stosuje rozwiązanie skryptu, jak wspomniano powyżej.

Wystarczy dodać link „Wyloguj się”, a po kliknięciu zwróć następujący HTML

    <div>You have been logged out. Redirecting to home...</div>    

<script>
    var XHR = new XMLHttpRequest();
    XHR.open("GET", "/Home/MyProtectedPage", true, "no user", "no password");
    XHR.send();

    setTimeout(function () {
        window.location.href = "/";
    }, 3000);
</script>

1

Ten JavaScript musi działać dla wszystkich przeglądarek najnowszej wersji:

//Detect Browser
var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
    // At least Safari 3+: "[object HTMLElementConstructor]"
var isChrome = !!window.chrome && !isOpera;              // Chrome 1+
var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
var Host = window.location.host;


//Clear Basic Realm Authentication
if(isIE){
//IE
    document.execCommand("ClearAuthenticationCache");
    window.location = '/';
}
else if(isSafari)
{//Safari. but this works mostly on all browser except chrome
    (function(safeLocation){
        var outcome, u, m = "You should be logged out now.";
        // IE has a simple solution for it - API:
        try { outcome = document.execCommand("ClearAuthenticationCache") }catch(e){}
        // Other browsers need a larger solution - AJAX call with special user name - 'logout'.
        if (!outcome) {
            // Let's create an xmlhttp object
            outcome = (function(x){
                if (x) {
                    // the reason we use "random" value for password is 
                    // that browsers cache requests. changing
                    // password effectively behaves like cache-busing.
                    x.open("HEAD", safeLocation || location.href, true, "logout", (new Date()).getTime().toString())
                    x.send("");
                    // x.abort()
                    return 1 // this is **speculative** "We are done." 
                } else {
                    return
                }
            })(window.XMLHttpRequest ? new window.XMLHttpRequest() : ( window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : u )) 
        }
        if (!outcome) {
            m = "Your browser is too old or too weird to support log out functionality. Close all windows and restart the browser."
        }
        alert(m);
        window.location = '/';
        // return !!outcome
    })(/*if present URI does not return 200 OK for GET, set some other 200 OK location here*/)
}
else{
//Firefox,Chrome
    window.location = 'http://log:out@'+Host+'/';
}

1

dodaj to do swojej aplikacji:

@app.route('/logout')
def logout():
    return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})

lepiej skorzystać z tego zwrotu: return („Wyloguj się”, 401)
Amir Mofakhar

1

wpisz chrome://restartpasek adresu i chrome, wszystkie aplikacje działające w tle, uruchomią się ponownie i pamięć podręczna haseł Auth zostanie wyczyszczona.


1

Dla przypomnienia istnieje nowy nagłówek odpowiedzi HTTP o nazwie Clear-Site-Data. Jeśli odpowiedź serwera zawiera Clear-Site-Data: "cookies"nagłówek, dane uwierzytelniające (nie tylko pliki cookie) powinny zostać usunięte. Testowałem to na Chrome 77, ale to ostrzeżenie pojawia się na konsoli:

Clear-Site-Data header on 'https://localhost:9443/clear': Cleared data types:
"cookies". Clearing channel IDs and HTTP authentication cache is currently not
supported, as it breaks active network connections.

Poświadczenia uwierzytelniania nie są usuwane, więc nie działa (na razie) w celu wdrożenia podstawowych wylogowań uwierzytelniania, ale być może w przyszłości tak się stanie. Nie testowałem w innych przeglądarkach.

Bibliografia:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data

https://www.w3.org/TR/clear-site-data/

https://github.com/w3c/webappsec-clear-site-data

https://caniuse.com/#feat=mdn-http_headers_clear-site-data_cookies


1

Wysyłanie https://invalid_login@hostnamedziała dobrze wszędzie oprócz Safari na Macu (cóż, nie zaznaczone Edge, ale też powinno tam działać).

Wylogowanie nie działa w przeglądarce Safari, gdy użytkownik wybierze opcję „zapamiętaj hasło” w wyskakującym okienku Uwierzytelnianie podstawowe HTTP. W takim przypadku hasło jest przechowywane w Dostępu do pęku kluczy (Finder> Aplikacje> Narzędzia> Dostęp do pęku kluczy (lub CMD + SPACJA i wpisz „Dostęp do pęku kluczy”)). Wysyłanie https://invalid_login@hostnamenie wpływa na dostęp do pęku kluczy, więc dzięki temu polu wyboru nie można się wylogować w Safari na Macu. Przynajmniej tak to dla mnie działa.

MacOS Mojave (10.14.6), Safari 12.1.2.

Poniższy kod działa dla mnie dobrze w Firefox (73), Chrome (80) i Safari (12). Gdy użytkownik przechodzi do strony wylogowania, kod jest wykonywany i upuszcza poświadczenia.

    //It should return 401, necessary for Safari only
    const logoutUrl = 'https://example.com/logout'; 
    const xmlHttp = new XMLHttpRequest();
    xmlHttp.open('POST', logoutUrl, true, 'logout');
    xmlHttp.send();

Również z jakiegoś powodu Safari nie zapisuje poświadczeń w wyskakującym okienku Podstawowego uwierzytelniania HTTP, nawet jeśli wybrano „zapamiętaj hasło”. Inne przeglądarki robią to poprawnie.


0
  • użyj identyfikatora sesji (ciasteczka)
  • unieważnij identyfikator sesji na serwerze
  • Nie akceptuj użytkowników z nieprawidłowymi identyfikatorami sesji

Dobrze jest również oferować uwierzytelnianie podstawowe jako zapasowy schemat logowania, gdy pliki cookie nie są dostępne.
bobince

0

Zaktualizowałem rozwiązanie mthoringu dla nowoczesnych wersji Chrome:

function logout(secUrl, redirUrl) {
    if (bowser.msie) {
        document.execCommand('ClearAuthenticationCache', 'false');
    } else if (bowser.gecko) {
        $.ajax({
            async: false,
            url: secUrl,
            type: 'GET',
            username: 'logout'
        });
    } else if (bowser.webkit || bowser.chrome) {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open(\"GET\", secUrl, true);
        xmlhttp.setRequestHeader(\"Authorization\", \"Basic logout\");\
        xmlhttp.send();
    } else {
// http://stackoverflow.com/questions/5957822/how-to-clear-basic-authentication-details-in-chrome
        redirUrl = url.replace('http://', 'http://' + new Date().getTime() + '@');
    }
    setTimeout(function () {
        window.location.href = redirUrl;
    }, 200);
}

-1
    function logout(secUrl, redirUrl) {
        if (bowser.msie) {
            document.execCommand('ClearAuthenticationCache', 'false');
        } else if (bowser.gecko) {
            $.ajax({
                async: false,
                url: secUrl,
                type: 'GET',
                username: 'logout'
            });
        } else if (bowser.webkit) {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", secUrl, true);
            xmlhttp.setRequestHeader("Authorization", "Basic logout");
            xmlhttp.send();
        } else {
            alert("Logging out automatically is unsupported for " + bowser.name
                + "\nYou must close the browser to log out.");
        }
        setTimeout(function () {
            window.location.href = redirUrl;
        }, 200);
    }

Próbowałem użyć powyższego w następujący sposób.

?php
    ob_start();
    session_start();
    require_once 'dbconnect.php';

    // if session is not set this will redirect to login page
    if( !isset($_SESSION['user']) ) {
        header("Location: index.php");
        exit;
    }
    // select loggedin users detail
    $res=mysql_query("SELECT * FROM users WHERE userId=".$_SESSION['user']);
    $userRow=mysql_fetch_array($res);
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Welcome - <?php echo $userRow['userEmail']; ?></title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css" type="text/css"  />
<link rel="stylesheet" href="style.css" type="text/css" />

    <script src="assets/js/bowser.min.js"></script>
<script>
//function logout(secUrl, redirUrl)
//bowser = require('bowser');
function logout(secUrl, redirUrl) {
alert(redirUrl);
    if (bowser.msie) {
        document.execCommand('ClearAuthenticationCache', 'false');
    } else if (bowser.gecko) {
        $.ajax({
            async: false,
            url: secUrl,
            type: 'GET',
            username: 'logout'
        });
    } else if (bowser.webkit) {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open("GET", secUrl, true);
        xmlhttp.setRequestHeader("Authorization", "Basic logout");
        xmlhttp.send();
    } else {
        alert("Logging out automatically is unsupported for " + bowser.name
            + "\nYou must close the browser to log out.");
    }
    window.location.assign(redirUrl);
    /*setTimeout(function () {
        window.location.href = redirUrl;
    }, 200);*/
}


function f1()
    {
       alert("f1 called");
       //form validation that recalls the page showing with supplied inputs.    
    }
</script>
</head>
<body>

    <nav class="navbar navbar-default navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="http://www.codingcage.com">Coding Cage</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="http://www.codingcage.com/2015/01/user-registration-and-login-script-using-php-mysql.html">Back to Article</a></li>
            <li><a href="http://www.codingcage.com/search/label/jQuery">jQuery</a></li>
            <li><a href="http://www.codingcage.com/search/label/PHP">PHP</a></li>
          </ul>
          <ul class="nav navbar-nav navbar-right">

            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
              <span class="glyphicon glyphicon-user"></span>&nbsp;Hi' <?php echo $userRow['userEmail']; ?>&nbsp;<span class="caret"></span></a>
              <ul class="dropdown-menu">
                <li><a href="logout.php?logout"><span class="glyphicon glyphicon-log-out"></span>&nbsp;Sign Out</a></li>
              </ul>
            </li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav> 

    <div id="wrapper">

    <div class="container">

        <div class="page-header">
        <h3>Coding Cage - Programming Blog</h3>
        </div>

        <div class="row">
        <div class="col-lg-12" id="div_logout">
        <h1 onclick="logout(window.location.href, 'www.espncricinfo.com')">MichaelA1S1! Click here to see log out functionality upon click inside div</h1>
        </div>
        </div>

    </div>

    </div>

    <script src="assets/jquery-1.11.3-jquery.min.js"></script>
    <script src="assets/js/bootstrap.min.js"></script>


</body>
</html>
<?php ob_end_flush(); ?>

Ale przekierowuje Cię tylko do nowej lokalizacji. Bez wylogowania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.