web-dev-qa-db-fra.com

Comment déconnecter l'utilisateur du site Web en utilisant l'authentification BASIC?

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

Tuer une session ne suffit pas, car une fois l'utilisateur 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.

Jusqu'à présent, la seule solution consiste à fermer le navigateur, mais cela n'est pas acceptable du point de vue de la convivialité.

251
Marko

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

Ce que vous devez faire, c’est que l’utilisateur clique sur un lien de déconnexion et envoie un message "401 non autorisé" en réponse, en utilisant le même domaine et au même niveau de dossier d’URL que le 401 normal que vous avez envoyé pour demander 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, en réponse, vous renvoyez une page "Vous vous êtes déconnecté avec succès". 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 passant les bonnes informations d'identification.

La question est de savoir si la zone de mot de passe quelque peu curieuse "ne saisissez pas votre mot de passe" rencontrera 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 reconnexion 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. L'une serait d'inclure le nom d'utilisateur actuel dans le lien de déconnexion (par exemple,/relogin? Nomutilisateur) et de rejeter lorsque les informations d'identification correspondent au nom d'utilisateur.

160
bobince

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

Avec Ajax, vous pouvez connecter votre lien/bouton "Déconnexion" à une fonction Javascript. Demandez à 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 façon, l'utilisateur ne verra jamais la boîte de dialogue de connexion supplémentaire lors de la déconnexion, ni ne devra se rappeler d'entrer de mauvaises informations d'identification.

192
system PAUSE

Demandez à l'utilisateur de cliquer sur un lien vers https: // log: [email protected]/ . Cela écrasera les informations d'identification existantes par des informations non valides; les déconnecter.

177
Matthew Welborn

Vous pouvez le faire entièrement en JavaScript:

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

document.execCommand("ClearAuthenticationCache")

Devrait retourner vrai quand cela fonctionne. Retourne false, undefined ou explose sur d'autres navigateurs.

Les nouveaux navigateurs (à compter de décembre 2012: Chrome, FireFox, Safari) ont un comportement "magique". S'ils voient une demande avec succès une authentification de base avec n'importe quel autre nom d'utilisateur fictif (disons logout), ils effacent le cache des informations d'identification et le définissent éventuellement pour ce nouveau nom d'utilisateur fictif, que vous devez créer. sure n'est pas un nom d'utilisateur valide pour afficher du contenu.

Exemple de base de cela est:

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

Une méthode "asynchrone" consiste à effectuer un appel AJAX à l'aide du 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 aussi en faire un 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*/);

63
ddotsenko

La fonction suivante est validé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 devez 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);
}
18
mthoring

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 se déconnecte sans lui montrer à nouveau la boîte de connexion du navigateur, puis le redirige vers une page déconnectée

11
Romuald Brunet

Ce n'est pas directement possible avec Basic-Authentication.

La spécification HTTP ne contient aucun mécanisme permettant au serveur d'indiquer au navigateur de ne plus envoyer les informations d'identification déjà présentées par l'utilisateur.

Il existe des "hacks" (voir d'autres réponses) impliquant généralement l'utilisation de XMLHttpRequest pour envoyer une requête HTTP avec des informations d'identification incorrectes pour remplacer celles fournies à l'origine.

10
Alnitak

C'est en fait assez simple.

Il suffit de visiter les éléments suivants dans votre navigateur et d’utiliser des informations d’identité incorrectes: http: // nom d'utilisateur: [email protected]

Cela devrait "vous déconnecter".

6
Chiedo

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"); 
      });
  });          
5
Claudio

Tout ce dont vous avez besoin est 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 autorisation 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>
2
Envek
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
Charlie
 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
Sushovan Mukherjee

Sur la base de ce que j'ai lu ci-dessus, j'ai obtenu une solution simple qui fonctionne sur n'importe quel navigateur:

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 efface l'utilisateur actuel et assume l'utilisateur "déconnexion".

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

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

2) Maintenant, lorsque l'utilisateur est revenu au fichier d'index normal, il essaie d'entrer automatiquement dans le système avec l'utilisateur "logout". Vous devez alors le bloquer en répondant avec 401 pour appeler la boîte de dialogue de connexion/mot de passe.

3) Il y a plusieurs façons de le faire. J'ai créé deux back-ends de connexion, l'un acceptant l'utilisateur déconnecté 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.

1
Foad

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

ajoutez ceci à votre application:

@app.route('/logout')
def logout():
    return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})
1
Amir Mofakhar
  • utiliser un identifiant de session (cookie)
  • invalider l'ID de session sur le serveur
  • Ne pas accepter les utilisateurs avec des identifiants de session non valides
0
Tomalak

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

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

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

0

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é.

0
Ali