Как выйти из системы с помощью BASIC-аутентификации? - PullRequest
243 голосов
/ 24 октября 2008

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

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

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

Ответы [ 19 ]

189 голосов
/ 29 января 2009

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

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

171 голосов
/ 09 октября 2013

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

156 голосов
/ 24 октября 2008

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

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

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

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

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

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

61 голосов
/ 15 января 2013

Вы можете сделать это полностью в 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*/);

16 голосов
/ 01 сентября 2015

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

Это невозможно напрямую при базовой аутентификации.

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

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

9 голосов
/ 10 июня 2014

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

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

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

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

6 голосов
/ 18 февраля 2015

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

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

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

5 голосов
/ 20 мая 2013

Это работает для 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"); 
      });
  });          
2 голосов
/ 13 марта 2015
 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;
}
...