Comment déconnecter un utilisateur du site Web en utilisant l'authentification de base?
est-il possible de déconnecter un utilisateur d'un site web s'il utilise une authentification de base?
tuer session n'est pas suffisant, puisque, une fois l'utilisateur est authentifié, chaque demande contient des informations de connexion, de sorte que l'utilisateur est automatiquement connecté la prochaine fois qu'il/elle accède au site en utilisant les mêmes justificatifs d'identité.
la seule solution jusqu'à présent est de fermer le navigateur, mais ce n'est pas acceptable du point de vue de la convivialité.
18 réponses
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 avez à faire est de demander à l'utilisateur de cliquer sur un lien de déconnexion, et d'envoyer un ‘401 non autorisé’ en réponse, en utilisant le même domaine et au même niveau de dossier URL que la normale 401 que vous envoyez demandant une connexion.
ils doivent être dirigés vers l'entrée de mauvais justificatifs d'identité suivant, par exemple. un nom d'utilisateur et un mot de passe vierges, et en réponse vous renvoyez "Vous êtes connecté avec succès" de la page. Les justificatifs d'identité erronés/Vierges écraseront alors les justificatifs d'identité corrects précédents.
en bref, le script de déconnexion inverse la logique du script de connexion, ne retournant la page de succès que si l'utilisateur n'est pas en passant les bonnes références.
la question Est de savoir si la boîte de mot de passe" n'entrez pas votre mot de passe", quelque peu curieuse, sera acceptée par l'utilisateur. Gestionnaires de mots de passe qui tentent de auto-remplir le mot de passe peut également obtenir de la manière ici.
Modifier pour ajouter en réponse au commentaire: re-log-in est un problème légèrement différent (sauf si vous avez besoin d'une déconnexion/connexion en deux étapes évidemment). Vous devez rejeter (401) la première tentative d'accéder au lien relogin, plutôt que d'accepter la seconde (qui a probablement un nom d'utilisateur/mot de passe différent). Il existe quelques façons dont vous pouvez faire cela. On serait d'inclure le nom d'utilisateur dans le lien de déconnexion (par exemple. /reconnectez-vous?nom d'utilisateur), et rejet lorsque les justificatifs correspondent au nom d'utilisateur.
Un complément à la réponse par bobince ...
avec Ajax vous pouvez avoir votre lien/bouton' Déconnexion ' relié à une fonction Javascript. Demandez à cette fonction d'envoyer le XMLHttpRequest avec un mauvais nom d'utilisateur et mot de passe. Ça devrait rapporter un 401. Puis définissez le document.emplacement retour à la page de pré-connexion. De cette façon, l'utilisateur ne verra jamais la boîte de dialogue de connexion supplémentaire pendant la déconnexion, ni n'aura à se rappeler de mettre de mauvaises références.
demandez à l'utilisateur de cliquer sur un lien vers https://log:out@example.com / . Cela écrasera les justificatifs d'identité existants avec ceux qui ne sont pas valides; les déconnecter.
vous pouvez le faire entièrement en JavaScript:
IE possède (depuis longtemps) une API standard pour effacer le cache D'authentification de base:
document.execCommand("ClearAuthenticationCache")
devrait revenir vrai quand ça marche. Renvoie false, undefined ou blows up sur d'autres navigateurs.
les nouveaux navigateurs (à partir de décembre 2012: Chrome, FireFox, Safari) ont un comportement" magique". S'ils voient une réussie demande d'autorisation de base avec tout faux autre nom d'utilisateur (disons logout
) ils effacent les informations d'identification du cache et peut-être le configurent pour ce nouveau nom d'utilisateur bidon, dont vous devez vous assurer qu'il ne s'agit pas d'un nom d'utilisateur valide pour visualiser 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@')
une façon" asynchrone "de faire ce qui précède est de faire 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 en faire un bookmarklet trop:
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*/);
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 pouvez vous déconnecter.
- redirUrl est l'url d'une zone non protégée par mot de passe (page de succès de déconnexion).
- vous pourriez augmenter le minuteur de redirection (actuellement 200ms).
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);
}
ce n'est pas directement possible avec Basic-Authentication.
il n'y a aucun mécanisme dans la spécification HTTP pour que le serveur dise au navigateur d'arrêter d'envoyer les informations d'identification que l'Utilisateur a déjà présentées.
il y a des" hacks " (voir autres réponses) impliquant typiquement l'utilisation de XMLHttpRequest pour envoyer une requête HTTP avec des informations d'identification incorrectes pour écraser ceux fournis à 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 de connexion sans lui montrer le navigateur se connecter à nouveau, puis le rediriger vers un déconnecté page
c'est en fait assez simple.
il suffit de visiter ce qui suit dans votre navigateur et d'utiliser des justificatifs d'identité erronés: http://username:password@yourdomain.com
Qui devrait "session".
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;
}
tout ce que vous avez besoin est rediriger l'utilisateur sur un certain logout URL et retourner 401 Unauthorized
erreur sur elle. Sur la page d'erreur (qui doit être accessible sans autorisation de base), vous devez fournir un lien complet vers votre page d'accueil (y compris scheme et hostname). L'utilisateur clique sur ce lien et le navigateur demande à nouveau des justificatifs d'identité.
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>
basé sur ce que j'ai lu ci-dessus, j'ai eu une solution simple qui fonctionne sur n'importe quel navigateur:
1) sur votre page de déconnexion vous appelez un ajax à votre fin arrière de connexion. Votre identifiant doit accepter de déconnexion de l'utilisateur. Une fois que l'extrémité arrière accepte, le navigateur effacer l'utilisateur actuel et suppose 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 index normal, il va essayer d'entrer automatiquement dans le système avec l'utilisateur "logout", sur ce la deuxième fois, vous devez le bloquer par réponse avec 401 pour invoquer la boîte de dialogue login/Mot de passe.
3) Il y a plusieurs façons de faire cela, j'ai créé deux back ends de connexion, un qui accepte l'utilisateur de déconnexion et un qui ne le fait pas. 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)
- invalider L'ID de session sur le serveur
- N'acceptez pas les utilisateurs avec des ID de session invalides
ce JavaScript doit fonctionner pour tous les navigateurs de la 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 demande:
@app.route('/logout')
def logout():
return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})
j'ai mis à jour la solution de 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($_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> Hi' <?php echo $userRow['userEmail']; ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="logout.php?logout"><span class="glyphicon glyphicon-log-out"></span> 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 il ne vous redirige à un nouvel endroit. Pas de déconnexion.