У меня была эта проблема, но ни одно из решений здесь не показало точно , что я хотел (я хочу, чтобы напечатанный вывод был допустимым выражением python), поэтому как насчет этого:
prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)
Использование:
>>> ugly = [9.0, 0.052999999999999999, 0.032575399999999997,
0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
>>> prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)
>>> print prettylist(ugly)
[9.00, 0.05, 0.03, 0.01, 0.06, 0.08]
(Я знаю, что формат .format () должен быть более стандартным решением, но я считаю это более читаемым)
Базовая проверка подлинности не была предназначена для управления протоколированием. Вы можете сделать это, но не полностью автоматически.
Что вам нужно сделать, так это нажать на ссылку выхода из системы и отправить ответ «401 несанкционированный» в ответ, используя ту же область и с тем же адресом уровень папки как обычный 401, который вы отправляете, запрашивая логин.
Они должны быть направлены для ввода неправильных учетных данных следующим образом, например. пустое имя пользователя и пароль, и в ответ вы отправляете страницу «Вы успешно вышли из системы». Неправильные / пустые учетные данные затем перезапишут предыдущие правильные учетные данные.
Короче говоря, сценарий выхода из строя инвертирует логику сценария входа, только возвращает страницу успеха, если пользователь не является передавая правильные учетные данные.
Вопрос в том, будет ли любопытный пароль «не вводить пароль», будет соответствовать принятию пользователем. Администраторы паролей, которые пытаются автозаполнять пароль, также могут попасть сюда.
Отредактируйте для добавления в ответ на комментарий: повторный вход в систему - это немного другая проблема (если вам не требуется двух- выход из системы / логин). Вы должны отклонить (401) первую попытку доступа к ссылке relogin, чем принять вторую (которая предположительно имеет другое имя пользователя / пароль). Есть несколько способов сделать это. Можно было бы указать текущее имя пользователя в ссылке выхода (например, имя пользователя / relogin?) И отклонить, когда учетные данные совпадут с именем пользователя.
Это невозможно напрямую с помощью Basic-Authentication.
В спецификации HTTP нет механизма для того, чтобы сервер сообщал браузеру о прекращении отправки учетных данных, которые пользователь уже представил.
Есть «хаки» (см. другие ответы), обычно связанные с использованием XMLHttpRequest для отправки HTTP-запроса с неправильными учетными данными для перезаписывания исходных данных.
добавьте это в ваше приложение:
@app.route('/logout')
def logout():
return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})
Этот JavaScript должен работать для всех браузеров последней версии:
//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+'/';
}
Попросите пользователя щелкнуть ссылку на https: // log: out@example.com/ . Это приведет к перезаписи существующих учетных данных с недопустимыми; выведение их из системы.
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;
}
На самом деле это довольно просто.
Просто зайдите в свой браузер и используйте неправильные учетные данные: http: // имя пользователя: пароль@yourdomain.com
Это должно «вывести вас».
Это работает для 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");
});
});
Вы можете сделать это целиком в JavaScript:
IE имеет (в течение длительного времени) стандартный API для очистки базового кэша аутентификации:
document.execCommand("ClearAuthenticationCache")
Должен возвращать true, когда он работает , Возвращает либо false, либо undefined, либо взрывается в других браузерах.
Новые браузеры (по состоянию на декабрь 2012: Chrome, FireFox, Safari) имеют «магическое» поведение. Если они видят успешный базовый запрос auth с любым фиктивным другим именем пользователя (скажем logout
), они очищают кеш учетных данных и, возможно, устанавливают его для этого нового имени пользователя с фиктивным именем, которое необходимо убедиться в том, что не действительное имя пользователя для просмотра содержимого.
. Основной пример:
var p = window.location.protocol + '//'
// current location must return 200 OK for this GET
window.location = window.location.href.replace(p, p + 'logout:password@')
. «Асинхронный» способ сделать это - сделать вызов AJAX, используя logout
. Пример:
(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*/)
Вы также можете сделать это букмарклет:
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*/);
logout
и / или выхода из системы?
– ulidtko
7 October 2013 в 20:30
logout
, существует и имеет сгенерированный пароль. В этом почти невероятно редком случае измените идентификатор пользователя на тот, который не будет существовать в вашей системе.
– davidjb
20 March 2014 в 07:58
<a href='javascript:......need*/);'>Logout</a>
– Eric
30 November 2015 в 07:57
Все, что вам нужно, - перенаправить пользователя на какой-то URL выхода и вернуть на него ошибку 401 Unauthorized
. На странице ошибок (которая должна быть доступна без базового auth) вам необходимо предоставить полную ссылку на вашу домашнюю страницу (включая схему и имя хоста).
Пример для 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;
}
Страница ошибки /home/user/errors/401.html
:
<!DOCTYPE html>
<p>You're not authorised. <a href="<!--# echo var="scheme" -->://<!--# echo var="host" -->/">Login</a>.</p>
Основываясь на том, что я прочитал выше, я получил простое решение, которое работает в любом браузере:
1) на странице выхода из системы вы вызываете ajax на свой логин. Ваш конец входа в систему должен принять пользователя для выхода из системы. После того, как задняя часть будет принята, браузер очистит текущего пользователя и примет пользователя «logout».
$.ajax({
async: false,
url: 'http://your_login_backend',
type: 'GET',
username: 'logout'
});
setTimeout(function () {
window.location.href = 'http://normal_index';
}, 200);
2) Теперь, когда пользователь вернется в обычный индексный файл, он попытается автоматически ввести система с пользователем «logout», во второй раз вы должны заблокировать ее с помощью ответа 401, чтобы вызвать диалог входа / пароля.
3) Есть много способов сделать это, я создал два входа back end, тот, который принимает пользователя выхода из системы, и тот, который этого не делает. Моя обычная страница входа использует тот, который не принимает, моя страница выхода из системы использует тот, который ее принимает.
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);
}
I tried using the above in the following way.
?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(); ?>
But it only redirects you to new location. No logout.
Я обновил решение mthoring для современных версий 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);
}
Подтверждена следующая функция для Firefox 40, Chrome 44, Opera 31 и IE 11. Bowser используется для обнаружения браузера, также используется jQuery. - secUrl - это URL-адрес защищенной паролем области, из которой выходить из системы. - redirUrl - это URL-адрес области, не защищенной паролем (страница успеха выхода из системы). - вы можете увеличить таймер переадресации (в настоящее время 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);
}
$.ajax
(async: false
), а вариант xmlhttp
- асинхронный (true
в open()
)?
– Bowi
14 September 2017 в 13:34
(bowser.gecko)
на (bowser.gecko || bowser.blink)
.
– Bowi
15 September 2017 в 14:10
Вот очень простой пример Javascript, в котором используется jQuery:
function logout(to_url) {
var out = window.location.href.replace(/:\/\//, '://log:out@');
jQuery.get(out).error(function() {
window.location = to_url;
});
}
Этот пользователь журнала отключен, снова не показывая ему окно входа в браузер, а затем перенаправляет его на в журнале ] page
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;
}
В дополнение к ответу bobince ...
С помощью Ajax вы можете подключить / отключить ссылку «Выход» к функции Javascript. Попросите эту функцию отправить XMLHttpRequest с плохим именем пользователя и паролем. Это должно вернуть 401. Затем верните документ.location на страницу предварительного входа. Таким образом, пользователь никогда не увидит дополнительное диалоговое окно входа в систему во время выхода из системы и не должен забывать вводить плохие учетные данные.