Как выйти из системы пользователя с веб-сайта с помощью обычной проверки подлинности?
можно ли выйти из пользователя с веб-сайта, если он использует обычную проверку подлинности?
убить сеанс недостаточно, так как, как только пользователь аутентифицируется, каждый запрос содержит информацию для входа, поэтому пользователь автоматически входит в систему в следующий раз, когда он/она обращается к сайту, используя те же учетные данные.
пока единственное решение-закрыть браузер, но это неприемлемо с точки зрения удобства использования.
18 ответов:
обычная проверка подлинности не предназначена для управления выходом из системы. Вы можете сделать это, но не полностью автоматически.
Что вам нужно сделать, это заставить пользователя щелкнуть ссылку выхода и отправить "401 несанкционированный" в ответ, используя ту же область и на том же уровне папки URL, что и обычный 401, который вы отправляете, запрашивая вход.
Они должны быть направлены на ввод неверных учетных данных далее, например. пустое имя пользователя и пароль, и в ответ вы отправляете обратно "у вас есть успешно вышел из системы " страница. Неправильные / пустые учетные данные будут перезаписаны предыдущими правильными учетными данными.
короче говоря, сценарий выхода из системы инвертирует логику сценария входа, возвращая страницу успеха только в том случае, если пользователь не передает данные.
вопрос в том, будет ли несколько любопытное поле пароля "не вводите пароль" соответствовать принятию пользователем. Менеджеры паролей, которые пытаются автоматически заполнить пароль, также могут получить сюда.
изменить, чтобы добавить в ответ на комментарий: повторный вход в систему-это немного другая проблема (если вам не требуется двухэтапный выход/вход, очевидно). Вы должны отклонить (401) первую попытку доступа к ссылке relogin, чем принять вторую (которая предположительно имеет другое имя пользователя/пароль). Есть несколько способов сделать это. Одним из них было бы включить текущее имя пользователя в ссылку выхода из системы (например. - релогин?имя пользователя), и отклонить, когда учетные данные совпадают с именем пользователя.
дополнение к ответу от bobince ...
с Ajax вы можете иметь свою ссылку/кнопку "Выход", подключенную к функции Javascript. Попросите эту функцию Отправить XMLHttpRequest с неверным именем пользователя и паролем. Это должно вернуть 401. Затем установите документ.расположение вернуться на страницу предварительного входа. Таким образом, пользователь никогда не будет видеть дополнительный диалог входа во время выхода из системы, и не нужно помнить, чтобы положить в плохие учетные данные.
пусть пользователь нажмет на ссылку https://log:out@example.com/. это перезапишет существующие учетные данные с недопустимыми; выход из системы.
вы можете сделать это полностью в 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*/);
подтверждена работа следующей функции для Firefox 40, Chrome 44, Opera 31 и IE 11.
Баузер используется для обнаружения браузера, 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); }
Это напрямую невозможно с помощью базовой аутентификации.
в спецификации HTTP нет механизма, чтобы сервер сообщал браузеру о прекращении отправки учетных данных, которые уже были представлены пользователем.
существуют" хаки " (см. другие ответы), обычно связанные с использованием XMLHttpRequest для отправки HTTP-запроса с неверными учетными данными для перезаписи первоначально предоставленных.
вот очень простой пример Javascript с использованием jQuery:
function logout(to_url) { var out = window.location.href.replace(/:\/\//, '://log:out@'); jQuery.get(out).error(function() { window.location = to_url; }); }
этот пользователь журнала выходит, не показывая ему окно входа в браузер снова, а затем перенаправить его на выход страница
Это на самом деле довольно просто.
просто посетите следующее в вашем браузере и используйте неправильные учетные данные: http://username:password@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"); }); });
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; }
все, что вам нужно, это перенаправить пользователя на какой-то URL выхода и вернуть
401 Unauthorized
ошибки на нем. На странице ошибки (которая должна быть доступна без базовой аутентификации) вам необходимо предоставить полную ссылку на вашу домашнюю страницу (включая схему и имя хоста). Пользователь нажимает на эту ссылку, и браузер снова запрашивает учетные данные.пример для 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 для вашего входа в систему. Ваш логин бэк-энд должен принять выход пользователя. Как только серверная часть принимает, браузер очищает текущего пользователя и принимает пользователя "выхода из системы".
$.ajax({ async: false, url: 'http://your_login_backend', type: 'GET', username: 'logout' }); setTimeout(function () { window.location.href = 'http://normal_index'; }, 200);
2) Теперь, когда пользователь вернулся к обычному индексному файлу, он попытается автоматически войти в систему с пользователем "выход", в этот второй раз вы должны заблокировать его ответьте с помощью 401, чтобы вызвать диалоговое окно логин / пароль.
3) Есть много способов сделать это, я создал два входа в систему, один из которых принимает пользователя выхода из системы, а другой-нет. моя обычная страница входа использует тот, который не принимает, моя страница выхода использует тот, который ее принимает.
- используйте идентификатор сеанса (cookie)
- аннулировать идентификатор сеанса на сервере
- не принимать пользователей с недопустимыми идентификаторами сеанса
этот 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+'/'; }
добавьте это в свое приложение:
@app.route('/logout') def logout(): return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})
я обновил решение 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); }
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); }
Я попытался использовать вышеизложенное следующим образом.
?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(); ?>
но он только перенаправляет вас на новое место. Нет выхода.