Domanda

È possibile disconnettere l'utente da un sito Web se utilizza l'autenticazione di base?

La sessione di uccisione non è sufficiente, poiché, una volta autenticato l'utente, ogni richiesta contiene informazioni di accesso, quindi l'utente accederà automaticamente al successivo accesso al sito utilizzando le stesse credenziali.

L'unica soluzione finora è chiudere il browser, ma non è accettabile dal punto di vista dell'usabilità.

È stato utile?

Soluzione

L'autenticazione di base non è stata progettata per gestire la disconnessione. Puoi farlo, ma non completamente automaticamente.

Quello che devi fare è fare in modo che l'utente faccia clic su un collegamento di logout e invii un & # 8216; 401 Non autorizzato & # 8217; in risposta, usando lo stesso regno e allo stesso livello di cartella URL del 401 normale che invii richiedendo un accesso.

Devono essere indirizzati a immettere successivamente credenziali errate, ad es. un nome utente e una password vuoti e in risposta invii & # 8220; Ti sei disconnesso correttamente & # 8221; pagina. Le credenziali errate / vuote sovrascriveranno quindi le precedenti credenziali corrette.

In breve, lo script di logout inverte la logica dello script di login, restituendo la pagina di successo solo se l'utente non è passando le giuste credenziali.

La domanda è se un po 'curioso & # 8220; non inserire la password & # 8221; la password verrà accettata dall'utente. I gestori di password che tentano di compilare automaticamente la password possono anche interferire qui.

Modifica per aggiungere in risposta al commento: il nuovo accesso è un problema leggermente diverso (a meno che non sia necessario un logout / login in due passaggi ovviamente). Devi rifiutare (401) il primo tentativo di accedere al collegamento di nuovo accesso, piuttosto che accettare il secondo (che presumibilmente ha un nome utente / password diversi). Ci sono alcuni modi per farlo. Uno sarebbe quello di includere il nome utente corrente nel collegamento di disconnessione (ad es. / Relogin? Nome utente) e rifiutarlo quando le credenziali corrispondono al nome utente.

Altri suggerimenti

Un'aggiunta alla risposta di bobince ...

Con Ajax puoi avere il tuo link / pulsante 'Logout' collegato ad una funzione Javascript. Chiedi a questa funzione di inviare XMLHttpRequest con un nome utente e una password errati. Questo dovrebbe restituire un 401. Quindi reimpostare document.location sulla pagina di pre-login. In questo modo, l'utente non vedrà mai la finestra di dialogo aggiuntiva durante il logout, né dovrà ricordarsi di inserire credenziali errate.

Chiedi all'utente di fare clic su un collegamento a https: // log: out@example.com/ . Ciò sovrascriverà le credenziali esistenti con quelle non valide; disconnettendoli.

Puoi farlo interamente in JavaScript:

IE ha (per molto tempo) un'API standard per cancellare la cache di autenticazione di base:

document.execCommand("ClearAuthenticationCache")

Dovrebbe restituire true quando funziona. Restituisce falso, indefinito o esplode su altri browser.

I nuovi browser (a partire da dicembre 2012: Chrome, FireFox, Safari) hanno " magic " comportamento. Se vedono una riuscita richiesta di autenticazione di base con qualsiasi altro nome utente fasullo (diciamo logout ) cancellano la cache delle credenziali e possibilmente la impostano per quel nuovo nome utente fasullo, che tu è necessario assicurarsi che non sia un nome utente valido per la visualizzazione dei contenuti.

Un esempio di base è:

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

Un " asincrono " modo di fare quanto sopra è quello di effettuare una chiamata AJAX utilizzando il nome utente logout . Esempio:

(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*/)

Puoi anche trasformarlo in un bookmarklet:

javascript: (function (c) {var a, b = " Dovresti essere disconnesso ora. " ;; 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 ", (nuova data) .getTime (). toString ()), a.send (" "), a = 1): a = void 0); a || ( b = " Il tuo browser è troppo vecchio o troppo strano per supportare la funzionalità di disconnessione. Chiudi tutte le finestre e riavvia il browser. "); alert (b)}) (/ * passa safeLocation qui se hai bisogno * /);

La seguente funzione è confermata funzionante per Firefox 40, Chrome 44, Opera 31 e IE 11.
Bowser viene utilizzato per il rilevamento del browser, viene utilizzato anche jQuery.

- secUrl è l'URL di un'area protetta da password da cui disconnettersi.
- redirUrl è l'URL di un'area non protetta da password (pagina di logout riuscita).
- potresti voler aumentare il timer di reindirizzamento (attualmente 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);
}

Questo non è direttamente possibile con l'autenticazione di base.

Non esiste alcun meccanismo nella specifica HTTP per il server per dire al browser di interrompere l'invio delle credenziali che l'utente ha già presentato.

Ci sono " hack " (vedi altre risposte) che in genere comportano l'utilizzo di XMLHttpRequest per inviare una richiesta HTTP con credenziali errate per sovrascrivere quelle originariamente fornite.

Ecco un esempio Javascript molto semplice usando jQuery:

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

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

Questo utente del log si disconnette senza mostrargli di nuovo la casella di accesso del browser, quindi reindirizzarlo a una pagina disconnesso

In realtà è piuttosto semplice.

Basta visitare quanto segue nel browser e utilizzare credenziali errate: http: // nome utente: password@tuodominio.com

Questo dovrebbe " disconnettersi " ;.

Funziona con 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"); 
      });
  });          
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;
}
 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;
}

Tutto ciò di cui hai bisogno è reindirizzare l'utente su alcuni URL di logout e restituire l'errore 401 non autorizzato . Nella pagina di errore (che deve essere accessibile senza autenticazione di base) è necessario fornire un collegamento completo alla home page (inclusi schema e nome host). L'utente farà clic su questo collegamento e il browser richiederà nuovamente le credenziali.

Esempio per 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;
}

Pagina di errore /home/user/errors/401.html :

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

Questo JavaScript deve funzionare per tutti i browser delle versioni più recenti:

//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+'/';
}

aggiungi questo alla tua applicazione:

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

Sulla base di quanto ho letto sopra ho ottenuto una soluzione semplice che funziona su qualsiasi browser:

1) nella pagina di disconnessione si chiama ajax al back-end di accesso. Il back-end di accesso deve accettare l'utente di disconnessione. Una volta che il back-end accetta, il browser cancella l'utente corrente e assume che il "logout" utente.

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

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

2) Ora, quando l'utente torna al normale file indice, proverà ad accedere automaticamente al sistema con l'utente " logout " ;, in questa seconda volta devi bloccarlo rispondendo con 401 per invocare il login / finestra di dialogo della password.

3) Esistono molti modi per farlo, ho creato due back-end di accesso, uno che accetta l'utente che si disconnette e uno che non lo fa. La mia normale pagina di accesso usa quella che non accetta, la mia pagina di logout usa quella che la accetta.

  • utilizza un ID sessione (cookie)
  • invalida l'ID sessione sul server
  • Non accettare utenti con ID sessione non validi

Ho aggiornato la soluzione di mthoring per le moderne versioni di 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);
}
    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);
    }

Ho provato a utilizzare quanto sopra nel modo seguente.

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

    // if session is not set this will redirect to login page
    if( !isset(
    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);
    }

Ho provato a utilizzare quanto sopra nel modo seguente.

<*>

Ma ti reindirizza solo verso una nuova posizione. Nessun logout.

SESSION['user']) ) { header("Location: index.php"); exit; } // select loggedin users detail $res=mysql_query("SELECT * FROM users WHERE userId=".
    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);
    }

Ho provato a utilizzare quanto sopra nel modo seguente.

<*>

Ma ti reindirizza solo verso una nuova posizione. Nessun logout.

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(); ?>

Ma ti reindirizza solo verso una nuova posizione. Nessun logout.

digita chrome: // restart nella barra degli indirizzi e chrome, con tutte le sue app in esecuzione in background, verrà riavviato e la cache della password di Auth verrà pulita.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top