Как выйти из системы с помощью BASIC-аутентификации?

http authentication basic-authentication

189517 просмотра

20 ответа

Можно ли выйти из системы с веб-сайта, если он использует обычную аутентификацию?

Сеанса убийства недостаточно, поскольку после аутентификации пользователя каждый запрос содержит информацию для входа в систему, поэтому пользователь автоматически регистрируется при следующем доступе к сайту с использованием тех же учетных данных.

Пока единственное решение - закрыть браузер, но это неприемлемо с точки зрения удобства использования.

Автор: Marko Источник Размещён: 12.11.2019 09:54

Ответы (20)


162 плюса

Решение

Обычная аутентификация не предназначена для управления выходом из системы. Вы можете сделать это, но не полностью автоматически.

Вам нужно, чтобы пользователь щелкнул ссылку выхода из системы и отправил «401 Unauthorized» в ответ, используя ту же область и тот же уровень URL-папки, что и обычный 401, который вы отправляете, запрашивая вход в систему.

Они должны быть направлены на ввод неправильных учетных данных, например. пустое имя пользователя и пароль, и в ответ вы отправляете обратно страницу «Вы успешно вышли из системы». Неверные / пустые учетные данные затем перезапишут предыдущие правильные учетные данные.

Короче говоря, сценарий выхода из системы инвертирует логику сценария входа в систему, возвращая страницу успеха, только если пользователь не передает правильные учетные данные.

Вопрос в том, будет ли достаточно любопытное поле для пароля «не вводить пароль» принятым пользователем. Менеджеры паролей, которые пытаются автоматически заполнить пароль, также могут помешать здесь.

Отредактируйте, чтобы добавить в ответ на комментарий: повторный вход - это немного другая проблема (если, конечно, вам не требуется двухэтапный выход из системы / вход в систему). Вы должны отклонить (401) первую попытку доступа к ссылке повторной регистрации, чем принять вторую (которая предположительно имеет другое имя пользователя / пароль). Есть несколько способов сделать это. Можно было бы включить текущее имя пользователя в ссылку выхода из системы (например, / relogin? Username) и отклонить, когда учетные данные соответствуют имени пользователя.

Автор: bobince Размещён: 24.10.2008 01:33

193 плюса

Дополнение к ответу от bobince ...

С Ajax вы можете привязать ссылку / кнопку «Выход» к функции Javascript. Пусть эта функция отправит XMLHttpRequest с неверным именем пользователя и паролем. Это должно вернуть 401. Затем верните document.location на страницу перед входом в систему. Таким образом, пользователь никогда не увидит дополнительное диалоговое окно входа в систему и не должен будет вводить неверные учетные данные.

Автор: system PAUSE Размещён: 29.01.2009 06:56

181 плюса

Попросите пользователя перейти по ссылке на https: // log: out@example.com/ . Это заменит существующие учетные данные недействительными; выходя из них.

Автор: Matthew Welborn Размещён: 08.10.2013 09:28

64 плюса

Вы можете сделать это полностью в JavaScript:

IE имеет (долгое время) стандартный API для очистки кэша базовой аутентификации:

document.execCommand("ClearAuthenticationCache")

Должен вернуть true, когда это работает. Возвращает либо false, undefined, либо взрывается в других браузерах.

Новые браузеры (по состоянию на декабрь 2012 года: Chrome, FireFox, Safari) имеют «магическое» поведение. Если они увидят успешный базовый запрос авторизации с любым поддельным другим именем пользователя (скажем 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*/);

Автор: ddotsenko Размещён: 15.01.2013 01:46

18 плюса

Подтверждено, что следующая функция работает для 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);
}

Автор: mthoring Размещён: 01.09.2015 07:24

11 плюса

Вот очень простой пример Javascript с использованием jQuery:

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

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

Этот пользователь выходит из системы, не показывая ему окно входа в браузер, а затем перенаправляет его на страницу выхода из системы.

Автор: Romuald Brunet Размещён: 10.06.2014 12:35

10 плюса

Это невозможно напрямую с Basic-Authentication.

В спецификации HTTP нет механизма для сервера, который бы указывал браузеру прекратить отправку учетных данных, которые пользователь уже представил.

Существуют «хаки» (см. Другие ответы), обычно включающие использование XMLHttpRequest для отправки HTTP-запроса с неверными учетными данными для перезаписи первоначально предоставленных.

Автор: Alnitak Размещён: 24.10.2008 01:30

6 плюса

Это на самом деле довольно просто.

Просто зайдите в браузер и используйте неверные учетные данные: http: // username: password@yourdomain.com

Это должно "выйти из системы".

Автор: Chiedo Размещён: 18.02.2015 06:59

5 плюса

Это работает для 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"); 
      });
  });          
Автор: Claudio Размещён: 20.05.2013 08:52

2 плюса

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;
}
Автор: Charlie Размещён: 06.02.2015 03:37

2 плюса

 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;
}
Автор: Sushovan Mukherjee Размещён: 13.03.2015 04:50

2 плюса

Все, что вам нужно, это перенаправить пользователя на некоторый 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>
Автор: Envek Размещён: 12.12.2015 02:12

1 плюс

Этот 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+'/';
}
Автор: Amit Shah Размещён: 21.07.2015 05:16

1 плюс

добавьте это в ваше приложение:

@app.route('/logout')
def logout():
    return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})
Автор: Amir Mofakhar Размещён: 18.09.2015 01:29

1 плюс

Исходя из того, что я прочитал выше, я получил простое решение, которое работает в любом браузере:

1) на странице выхода вы вызываете ajax для своей учетной записи. Ваш бэкэнд должен принять пользователя из системы. Как только бэкэнд примет, браузер очищает текущего пользователя и принимает пользователя "выхода из системы".

$.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) Есть много способов сделать это, я создал два бэкэнда входа в систему, один из которых принимает пользователя, а другой нет. Моя обычная страница входа использует ту, которая не принимает, моя страница выхода использует ту, которая ее принимает.

Автор: Foad Размещён: 02.03.2017 03:45

0 плюса

  • использовать идентификатор сеанса (cookie)
  • сделать недействительным идентификатор сеанса на сервере
  • Не принимать пользователей с неверными идентификаторами сеансов
Автор: Tomalak Размещён: 24.10.2008 01:24

0 плюса

Я обновил решение 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);
}
Автор: Max Размещён: 15.05.2017 11:15

0 плюса

<div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-html lang-html prettyprint-override">    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>&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(); ?>

Но это только перенаправляет вас на новое место. Нет выхода.

Автор: Hasan Junaid Hashmi Размещён: 09.01.2017 10:29

0 плюса

введите chrome://restartв адресную строку, и Chrome, со всеми приложениями, работающими в фоновом режиме, перезапустится и очистит кэш пароля Auth.

Автор: Ali Размещён: 16.04.2019 09:37

0 плюса

Просто для записи есть новый заголовок ответа HTTP Clear-Site-Data. Если ваш ответ сервера содержит Clear-Site-Data: "cookies"заголовок, то учетные данные для аутентификации (не только файлы cookie) должны быть удалены. Я тестировал его на Chrome 77, но на консоли отображается это предупреждение:

Clear-Site-Data header on 'https://localhost:9443/clear': Cleared data types:
"cookies". Clearing channel IDs and HTTP authentication cache is currently not
supported, as it breaks active network connections.

И учетные данные аутентификации не удаляются, поэтому это не работает (пока) для реализации основных выходов из системы аутентификации, но, возможно, в будущем это удастся. Не тестировал в других браузерах.

Рекомендации:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data

https://www.w3.org/TR/clear-site-data/

https://github.com/w3c/webappsec-clear-site-data

https://caniuse.com/#feat=mdn-http_headers_clear-site-data_cookies

Автор: Nahuel Greco Размещён: 15.09.2019 11:14
Вопросы из категории :
32x32