HTTP認証で保護されたフォルダからログアウトする正しい方法は何ですか?
これを達成できる回避策はありますが、バグがあったり、特定の状況やブラウザーで機能しない可能性があるため、潜在的に危険です。だからこそ、私は正しくてきれいな解決策を探しています。
HTTP認証で保護されたフォルダからログアウトする正しい方法は何ですか?
これを達成できる回避策はありますが、バグがあったり、特定の状況やブラウザーで機能しない可能性があるため、潜在的に危険です。だからこそ、私は正しくてきれいな解決策を探しています。
ムー。正しい方法は存在せず、ブラウザ間で一貫している方法もありません。
これは、HTTP仕様(セクション15.6)に起因する問題です。
既存のHTTPクライアントとユーザーエージェントは通常、認証情報を無期限に保持します。HTTP/1.1。サーバーがこれらのキャッシュされたクレデンシャルを破棄するようにクライアントに指示する方法を提供しません。
一方、セクション10.4.2には次のように書かれています。
要求にすでに許可資格情報が含まれている場合、401応答は、それらの資格情報の許可が拒否されたことを示します。401応答に前の応答と同じチャレンジが含まれ、ユーザーエージェントがすでに少なくとも1回認証を試みた場合、そのエンティティには関連する診断情報が含まれている可能性があるため、ユーザーには応答で指定されたエンティティを提示する必要があります。
言い換えると、(@ Karstenが言うように)ログインボックスを再度表示できる場合がありますが、ブラウザーは要求を受け入れる必要はありません。したがって、この(誤った)機能にあまり依存しないでください。
Safariでうまく機能する方法。Firefox と Opera でも動作しますが、警告が表示されます。
Location: http://logout@yourserver.example.com/
これにより、以前のユーザー名を上書きして、新しいユーザー名で URL を開くようブラウザに指示します。
簡単な答えは、http 認証から確実にログアウトできないということです。
長い答え:
Http-auth (他の HTTP 仕様と同様) はステートレスであることを意図しています。したがって、「ログイン」または「ログアウト」は、実際には意味のある概念ではありません。それを確認するより良い方法は、HTTP リクエストごとに (ページの読み込みは通常複数のリクエストであることを思い出してください)、「リクエストしていることを実行してもよいですか?」と尋ねることです。サーバーは、各リクエストを新しいものとして認識し、以前のリクエストとは無関係です。
ブラウザーは、最初の 401 でユーザーが伝えた資格情報を記憶し、その後の要求でユーザーの明示的な許可なしにそれらを再送信することを選択しました。これは、ユーザーが期待する「ログイン/ログアウト」モデルをユーザーに提供しようとする試みですが、これは単なるお世辞です。この状態の永続性をシミュレートしているのはブラウザーです。Web サーバーはそれをまったく認識していません。
したがって、http-auth のコンテキストでの「ログアウト」は、ブラウザによって提供される純粋なシミュレーションであり、サーバーの権限外です。
はい、クラッジがあります。しかし、それらは RESTful 性を壊し (それがあなたにとって価値がある場合)、信頼性が低くなります。
サイト認証にログイン/ログアウト モデルが絶対に必要な場合、最適な方法は追跡 Cookie であり、何らかの方法 (mysql、sqlite、flatfile など) でサーバーに状態の永続性が保存されます。これには、たとえば PHP を使用して、すべてのリクエストを評価する必要があります。
回避策
Javascript を使用してこれを行うことができます。
<html><head>
<script type="text/javascript">
function logout() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
// code for IE
else if (window.ActiveXObject) {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if (window.ActiveXObject) {
// IE clear HTTP Authentication
document.execCommand("ClearAuthenticationCache");
window.location.href='/where/to/redirect';
} else {
xmlhttp.open("GET", '/path/that/will/return/200/OK', true, "logout", "logout");
xmlhttp.send("");
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {window.location.href='/where/to/redirect';}
}
}
return false;
}
</script>
</head>
<body>
<a href="#" onclick="logout();">Log out</a>
</body>
</html>
上記で行われることは次のとおりです。
IE の場合 - 認証キャッシュをクリアして、どこかにリダイレクトするだけです
他のブラウザの場合- 「ログアウト」ログイン名とパスワードを使用して、バックグラウンドで XMLHttpRequest を送信します。そのリクエストに 200 OK を返す何らかのパスにそれを送信する必要があります (つまり、HTTP 認証を必要としません)。
'/where/to/redirect'
ログアウト後にリダイレクトするパスに置き換え'/path/that/will/return/200/OK'
、200 OK を返すサイト上のパスに置き換えます。
回避策(クリーンでナイスな(または機能している!コメントを参照)ソリューションではありません):
彼の資格情報を一度無効にします。
適切なヘッダーを送信することで、HTTP 認証ロジックを PHP に移行できます (ログインしていない場合)。
Header('WWW-Authenticate: Basic realm="protected area"');
Header('HTTP/1.0 401 Unauthorized');
入力を次のように解析します。
$_SERVER['PHP_AUTH_USER'] // httpauth-user
$_SERVER['PHP_AUTH_PW'] // httpauth-password
したがって、彼の資格情報を一度無効にするのは簡単です。
問題に対する私の解決策は次のとおりです。このページの 2 番目の例では、関数http_digest_parse
を見つけることができます: http://php.net/manual/en/features.http-auth.php。$realm
$users
session_start();
function LogOut() {
session_destroy();
session_unset($_SESSION['session_id']);
session_unset($_SESSION['logged']);
header("Location: /", TRUE, 301);
}
function Login(){
global $realm;
if (empty($_SESSION['session_id'])) {
session_regenerate_id();
$_SESSION['session_id'] = session_id();
}
if (!IsAuthenticated()) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.$_SESSION['session_id'].'",opaque="'.md5($realm).'"');
$_SESSION['logged'] = False;
die('Access denied.');
}
$_SESSION['logged'] = True;
}
function IsAuthenticated(){
global $realm;
global $users;
if (empty($_SERVER['PHP_AUTH_DIGEST']))
return False;
// check PHP_AUTH_DIGEST
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
!isset($users[$data['username']]))
return False;// invalid username
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
// Give session id instead of data['nonce']
$valid_response = md5($A1.':'.$_SESSION['session_id'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if ($data['response'] != $valid_response)
return False;
return True;
}
「Password protected」という名前の HTTP 基本認証レルムがあり、Bob がログインしているとします。ログアウトするには、2 つの AJAX リクエストを作成します。
WWW-Authenticate: Basic realm="Password protected"
この時点で、ブラウザはボブの資格情報を忘れています。
通常、ブラウザーがユーザーに資格情報を要求し、特定の Web サイトにそれらを提供すると、それ以上のプロンプトは表示されずに継続します。クライアント側で Cookie をクリアするさまざまな方法とは異なり、提供された認証資格情報をブラウザーに忘れさせる同様の方法を私は知りません。
Trac はデフォルトで HTTP 認証も使用します。ログアウトが機能せず、修正できません:
- これは HTTP 認証スキーム自体の問題であり、Trac で適切に修正することはできません。
- 現在、すべての主要なブラウザーで機能する回避策 (JavaScript またはその他) はありません。
送信元: http://trac.edgewall.org/ticket/791#comment:103
この問題は 7 年前に報告されており、HTTP はステートレスです。要求が認証資格情報を使用して行われるかどうか。しかし、それはリクエストを受信するサーバーではなく、リクエストを送信するクライアントの問題です。サーバーは、リクエスト URI に承認が必要かどうかしか判断できません。
.htaccess 認証をリセットする必要があったため、これを使用しました。
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
}
?>
ここで見つけました: http://php.net/manual/en/features.http-auth.php
図に行きます。
そのページには多くの解決策があり、下部にも記載されています:Lynxは、他のブラウザのように認証をクリアしません;)
インストール済みのブラウザーでテストしたところ、一度閉じると、各ブラウザーは再入力時に一貫して再認証が必要なようです。
多分私は要点を逃しています。
HTTP認証を終了するために私が見つけた最も信頼できる方法は、ブラウザーとすべてのブラウザーウィンドウを閉じることです。Javascriptを使用してブラウザウィンドウを閉じることはできますが、すべてのブラウザウィンドウを閉じることができるとは思いません。
これまでに見つけた最良の解決策は次のとおりです(これは一種の疑似コードであり、$isLoggedIn
http認証の疑似変数です):
「ログアウト」時に、ユーザーが実際にログアウトしたことを示す情報をセッションに保存するだけです。
function logout()
{
//$isLoggedIn = false; //This does not work (point of this question)
$_SESSION['logout'] = true;
}
認証を確認する場所で、条件を展開します。
function isLoggedIn()
{
return $isLoggedIn && !$_SESSION['logout'];
}
セッションは http 認証の状態に多少関連しているため、ユーザーがブラウザを開いたままにし、http 認証がブラウザで持続している限り、ユーザーはログアウトしたままになります。
私の知る限り、htaccess (つまり HTTP ベースの) 認証を使用する場合、「ログアウト」機能を実装するクリーンな方法はありません。
これは、このような認証では HTTP エラー コード '401' を使用して、資格情報が必要であることをブラウザーに伝えるためです。この時点で、ブラウザーはユーザーに詳細を求めるプロンプトを表示します。それ以降、ブラウザーが閉じられるまで、それ以上のプロンプトを表示することなく、常に資格情報が送信されます。
他の人は基本的なhttp認証からログアウトすることは不可能であると言っているのは正しいですが、同様に動作する認証を実装する方法があります。明らかなアプローチの1つは、auth_memcookieを使用することです。これを使用して基本HTTP認証を本当に実装したい場合(つまり、HTTPフォームではなくブラウザダイアログを使用してログインする場合)-認証を、ユーザーが後に来た場所にリダイレクトするPHPスクリプトを含む別の.htaccess保護ディレクトリに設定するだけですmemcacheセッションを作成します。
解決策を記事 ( https://www.hattonwebsolutions.co.uk/articles/how_to_logout_of_http_sessions ) にまとめましたが、ajax 呼び出しと 2x htaccess ファイルを使用しました (この質問で提案されているように: HTTP 認証からログアウトする方法) 。 (htaccess) は Google Chrome で動作しますか? )。
要するに - あなた:
これにより、別のユーザー名を要求する (ユーザーを混乱させる) ログアウト フォルダーに 2 番目のポップアップが表示されるのを回避できます。私の記事では Jquery を使用していますが、これを回避できるはずです。