基本認証を使用している場合、Web サイトからユーザーをログアウトすることはできますか?
ユーザーが認証されると、各リクエストにログイン情報が含まれるため、セッションを強制終了するだけでは不十分です。そのため、ユーザーは次回同じ資格情報を使用してサイトにアクセスするときに自動的にログインします。
これまでの唯一の解決策はブラウザを閉じることですが、それはユーザビリティの観点からは受け入れられません。
基本認証を使用している場合、Web サイトからユーザーをログアウトすることはできますか?
ユーザーが認証されると、各リクエストにログイン情報が含まれるため、セッションを強制終了するだけでは不十分です。そのため、ユーザーは次回同じ資格情報を使用してサイトにアクセスするときに自動的にログインします。
これまでの唯一の解決策はブラウザを閉じることですが、それはユーザビリティの観点からは受け入れられません。
ユーザーにhttps://log:out@example.com/へのリンクをクリックしてもらいます。これにより、既存の資格情報が無効な資格情報で上書きされます。それらをログアウトします。
bobinceによる答えへの追加...
Ajaxを使用すると、「ログアウト」リンク/ボタンをJavascript関数に接続できます。この関数に、不正なユーザー名とパスワードを使用してXMLHttpRequestを送信させます。これで401が返されます。次に、document.locationをログイン前のページに戻します。このように、ユーザーはログアウト中に追加のログインダイアログを表示することはなく、不正なクレデンシャルを入力することを忘れないでください。
基本認証は、ログアウトを管理するようには設計されていません。あなたはそれを行うことができますが、完全に自動ではありません。
あなたがしなければならないことは、ユーザーにログアウトリンクをクリックさせ、ログインを要求するために送信する通常の 401 と同じレルムと同じ URL フォルダーレベルを使用して、応答として「401 Unauthorized」を送信することです。
次に間違った資格情報を入力するように指示する必要があります。空白のユーザー名とパスワードを入力すると、「正常にログアウトしました」というページが返されます。間違った/空白の資格情報は、以前の正しい資格情報を上書きします。
つまり、ログアウト スクリプトはログイン スクリプトのロジックを逆にして、ユーザーが正しい資格情報を渡さない場合にのみ成功ページを返します。
問題は、やや奇妙な「パスワードを入力しないでください」というパスワード ボックスがユーザーに受け入れられるかどうかです。パスワードを自動入力しようとするパスワードマネージャーも、ここで邪魔になる可能性があります.
コメントに応じて編集して追加します。再ログインは、わずかに異なる問題です (明らかに 2 段階のログアウト/ログインが必要な場合を除きます)。再ログイン リンクにアクセスする最初の試行を拒否 (401) する必要があります。これを行うにはいくつかの方法があります。1 つは、現在のユーザー名をログアウト リンク (例: /relogin?username) に含め、資格情報がユーザー名と一致する場合に拒否することです。
JavaScript で完全に実行できます。
IE には (長い間) 基本認証キャッシュをクリアするための標準 API があります。
document.execCommand("ClearAuthenticationCache")
動作する場合は true を返す必要があります。false、undefined を返すか、他のブラウザでは失敗します。
新しいブラウザ (2012 年 12 月現在: 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@')
上記を行う「非同期」の方法は、logout
ユーザー名を利用して AJAX 呼び出しを行うことです。例:
(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*/);
これは、Basic-Authentication では直接可能ではありません。
HTTP 仕様には、ユーザーが既に提示した資格情報の送信を停止するようにサーバーがブラウザに指示するメカニズムはありません。
通常、XMLHttpRequest を使用して不正な資格情報を含む HTTP 要求を送信し、最初に提供された資格情報を上書きする「ハック」(他の回答を参照) があります。
それは実際には非常に簡単です。
ブラウザで以下にアクセスして、間違った認証情報を使用してください: 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");
});
});
必要なのは、ログアウト URL でユーザーをリダイレクトし、その 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>
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;
}