Question

Est-il possible de déconnecter l'utilisateur d'un site Web s'il utilise l'authentification de base?

La session de mise à mort ne suffit pas, car une fois que l'utilisateur est authentifié, chaque demande contient des informations de connexion. L'utilisateur est donc automatiquement connecté la prochaine fois qu'il accédera au site avec les mêmes informations d'identification.

La seule solution à ce jour consiste à fermer le navigateur, mais cela n’est pas acceptable du point de vue de la convivialité.

Était-ce utile?

La solution

L’authentification de base n’était pas conçue pour gérer la déconnexion. Vous pouvez le faire, mais pas complètement automatiquement.

Vous devez demander à l'utilisateur de cliquer sur un lien de déconnexion et d'envoyer un message & # 8216; 401 non autorisé & # 8217; en réponse, en utilisant le même domaine et au même niveau de dossier d'URL que le 401 normal que vous envoyez en demandant une connexion.

Ils doivent être dirigés de manière à entrer les informations d'identification erronées ensuite, par exemple. un nom d'utilisateur et un mot de passe vierges et vous recevrez en réponse un & # 8220; vous vous êtes déconnecté avec succès & # 8221; page. Les informations d'identification incorrectes / vides écraseront les informations d'identification précédentes correctes.

En bref, le script de déconnexion inverse la logique du script de connexion en ne renvoyant la page de réussite que si l'utilisateur n'est pas en train de transmettre les informations d'identification correctes.

La question est de savoir si le curieux & # 8220; n'entrez pas votre mot de passe & # 8221; mot de passe répondra l'acceptation de l'utilisateur. Les gestionnaires de mots de passe qui tentent de saisir automatiquement le mot de passe peuvent également s'y opposer.

Modifier pour ajouter en réponse au commentaire: la réouverture de session est un problème légèrement différent (à moins que vous ne souhaitiez évidemment une déconnexion / connexion en deux étapes). Vous devez rejeter (401) la première tentative d'accès au lien de reconnexion, puis accepter la seconde (qui a vraisemblablement un nom d'utilisateur / mot de passe différent). Vous pouvez le faire de plusieurs manières. Une solution consisterait à inclure le nom d'utilisateur actuel dans le lien de déconnexion (par exemple, / relogin? Nomutilisateur) et à rejeter lorsque les informations d'identification correspondent au nom d'utilisateur.

Autres conseils

Un ajout à la réponse de bobince ...

Avec Ajax, vous pouvez associer votre lien / bouton "Déconnexion" à une fonction Javascript. Demander à cette fonction d’envoyer XMLHttpRequest avec un nom d’utilisateur et un mot de passe incorrects. Cela devrait revenir à 401. Ensuite, définissez document.location sur la page de pré-connexion. De cette manière, l'utilisateur ne verra jamais la boîte de dialogue de connexion supplémentaire lors de la déconnexion, ni ne devra penser à entrer de mauvaises informations d'identification.

Demandez à l'utilisateur de cliquer sur un lien vers https: // log: out@example.com/ . Cela écrasera les informations d'identification existantes par des informations non valides; les déconnecter.

Vous pouvez le faire entièrement en JavaScript:

IE dispose (pendant longtemps) d'une API standard pour vider le cache d'authentification de base:

document.execCommand("ClearAuthenticationCache")

Doit retourner true quand cela fonctionne. Renvoie false, non défini ou explose sur les autres navigateurs.

Les nouveaux navigateurs (à compter de décembre 2012: Chrome, FireFox, Safari) ont "magique". comportement. S'ils voient une demande d'autorisation de base réussie avec n'importe quel autre nom d'utilisateur fictif (disons déconnexion ), ils effacent le cache des informations d'identification et le définissent éventuellement pour ce nouveau nom d'utilisateur fictif. devez vous assurer que le nom d'utilisateur n'est pas valide pour afficher le contenu.

Exemple de 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 " asynchrone " Pour effectuer ce qui précède, vous pouvez effectuer un appel AJAX en utilisant le nom d'utilisateur logout . Exemple:

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

Vous pouvez également en faire un bookmarklet:

javascript: (function (c) {var a, b = "vous devez être déconnecté maintenant." try {a = document.execCommand (& clear; ClearAuthenticationCache &))} catch (d) { } a || ((a = window.XMLHttpRequest? nouvelle fenêtre.XMLHttpRequest: window.ActiveXObject? nouveau ActiveXObject (" Microsoft.XMLHTTP &);: void 0)? (a.open (& HEAD ", c || location .href,! 0, "logout", (nouvelle date) .getTime (). toString ()), a.send ("quot"), a = 1): a = vide 0); a || b = "Votre navigateur est trop ancien ou trop bizarre pour prendre en charge la fonctionnalité de déconnexion. Fermez toutes les fenêtres et redémarrez le navigateur."; alert (b)}) (/ * passez safeLocation ici si vous avez besoin de * /);

La fonction suivante est confirmée pour Firefox 40, Chrome 44, Opera 31 et IE 11.
Bowser est utilisé pour la détection du navigateur, jQuery est également utilisé.

- secUrl est l'URL d'une zone protégée par mot de passe à partir de laquelle vous déconnecter.
- redirUrl est l'URL d'une zone non protégée par mot de passe (page de déconnexion réussie).
- vous souhaiterez peut-être augmenter le délai de redirection (actuellement 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);
}

Ceci n'est pas directement possible avec l'authentification de base.

Il n'y a dans la spécification HTTP aucun mécanisme permettant au serveur d'indiquer au navigateur de ne plus envoyer les informations d'identification que l'utilisateur a déjà présentées.

Il y a des "hacks" (Voir autres réponses) impliquant généralement l’utilisation de XMLHttpRequest pour envoyer une requête HTTP avec des informations d’identification incorrectes pour écraser celles fournies à l’origine.

Voici un exemple Javascript très simple utilisant jQuery:

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

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

Cet utilisateur est déconnecté sans lui montrer à nouveau la zone de connexion du navigateur, puis redirigé vers une page déconnectée

.

C'est en fait assez simple.

Il suffit de visiter les éléments suivants dans votre navigateur et d'utiliser des informations d'identification incorrectes: http: // nom d'utilisateur: motdepasse@votredomaine.com

Cela devrait vous "déconnecter".

Cela fonctionne pour 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;
}

Il vous suffit de rediriger l'utilisateur sur une URL de déconnexion et de renvoyer l'erreur 401 Unauthorized . Sur la page d'erreur (qui doit être accessible sans l'authentification de base), vous devez fournir un lien complet vers votre page d'accueil (schéma et nom d'hôte compris). L'utilisateur cliquera sur ce lien et le navigateur demandera à nouveau les informations d'identification.

Exemple pour 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;
}

Page d'erreur /home/user/errors/401.html :

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

Ce JavaScript doit fonctionner pour tous les navigateurs de dernière version:

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

ajoutez ceci à votre application:

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

Sur la base de ce que j'ai lu ci-dessus, j'ai obtenu une solution simple qui fonctionne sur tous les navigateurs:

1) sur votre page de déconnexion, vous appelez un ajax à votre connexion. Votre connexion back-end doit accepter l'utilisateur de déconnexion. Une fois le back-end accepté, le navigateur supprime l'utilisateur actuel et assume la "déconnexion". utilisateur.

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

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

2) Lorsque l'utilisateur est revenu au fichier d'index normal, il essaiera d'entrer automatiquement dans le système avec l'utilisateur "logout", cette fois-ci, vous devrez le bloquer en répondant avec 401 pour invoquer le login / dialogue de mot de passe.

3) Il existe de nombreuses façons de le faire. J'ai créé deux back-ends de connexion, l'un acceptant l'utilisateur de déconnexion et l'autre non. Ma page de connexion normale utilise celle qui n’accepte pas, ma page de déconnexion utilise celle qui l’accepte.

  • utiliser un identifiant de session (cookie)
  • invalide l'ID de session sur le serveur
  • Ne pas accepter les utilisateurs avec des identifiants de session non valides

J'ai mis à jour la solution mthoring pour les versions modernes de 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);
    }

J'ai essayé d'utiliser ce qui précède de la manière suivante.

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

J'ai essayé d'utiliser ce qui précède de la manière suivante.

<*>

Mais cela ne vous redirige que vers un nouvel emplacement. Pas de déconnexion.

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

J'ai essayé d'utiliser ce qui précède de la manière suivante.

<*>

Mais cela ne vous redirige que vers un nouvel emplacement. Pas de déconnexion.

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

Mais cela ne vous redirige que vers un nouvel emplacement. Pas de déconnexion.

tapez chrome: // restart dans la barre d'adresse et chrome, avec toutes ses applications s'exécutant en arrière-plan, redémarrera et le cache du mot de passe d'authentification sera nettoyé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top