152

HTTP認証で保護されたフォルダからログアウトする正しい方法は何ですか?

これを達成できる回避策はありますが、バグがあったり、特定の状況やブラウザーで機能しない可能性があるため、潜在的に危険です。だからこそ、私は正しくてきれいな解決策を探しています。

4

18 に答える 18

103

ムー。正しい方法は存在せず、ブラウザ間で一貫している方法もありません。

これは、HTTP仕様(セクション15.6)に起因する問題です。

既存のHTTPクライアントとユーザーエージェントは通常、認証情報を無期限に保持します。HTTP/1.1。サーバーがこれらのキャッシュされたクレデンシャルを破棄するようにクライアントに指示する方法を提供しません。

一方、セクション10.4.2には次のように書かれています。

要求にすでに許可資格情報が含まれている場合、401応答は、それらの資格情報の許可が拒否されたことを示します。401応答に前の応答と同じチャレンジが含まれ、ユーザーエージェントがすでに少なくとも1回認証を試みた場合、そのエンティティには関連する診断情報が含まれている可能性があるため、ユーザーには応答で指定されたエンティティを提示する必要があります。

言い換えると、(@ Karstenが言うように)ログインボックスを再度表示できる場合がありますが、ブラウザーは要求を受け入れる必要はありません。したがって、この(誤った)機能にあまり依存しないでください。

于 2009-01-16T09:06:46.440 に答える
62

Safariでうまく機能する方法。Firefox と Opera でも動作しますが、警告が表示されます。

Location: http://logout@yourserver.example.com/

これにより、以前のユーザー名を上書きして、新しいユーザー名で URL を開くようブラウザに指示します。

于 2009-01-21T21:17:50.693 に答える
46

簡単な答えは、http 認証から確実にログアウトできないということです。

長い答え:
Http-auth (他の HTTP 仕様と同様) はステートレスであることを意図しています。したがって、「ログイン」または「ログアウト」は、実際には意味のある概念ではありません。それを確認するより良い方法は、HTTP リクエストごとに (ページの読み込みは通常複数のリクエストであることを思い出してください)、「リクエストしていることを実行してもよいですか?」と尋ねることです。サーバーは、各リクエストを新しいものとして認識し、以前のリクエストとは無関係です。

ブラウザーは、最初の 401 でユーザーが伝えた資格情報を記憶し、その後の要求でユーザーの明示的な許可なしにそれらを再送信することを選択しました。これは、ユーザーが期待する「ログイン/ログアウト」モデルをユーザーに提供しようとする試みですが、これは単なるお世辞です。この状態の永続性をシミュレートしているのはブラウザーです。Web サーバーはそれをまったく認識していません。

したがって、http-auth のコンテキストでの「ログアウト」は、ブラウザによって提供される純粋なシミュレーションであり、サーバーの権限外です。

はい、クラッジがあります。しかし、それらは RESTful 性を壊し (それがあなたにとって価値がある場合)、信頼性が低くなります。

サイト認証にログイン/ログアウト モデルが絶対に必要な場合、最適な方法は追跡 Cookie であり、何らかの方法 (mysql、sqlite、flatfile など) でサーバーに状態の永続性が保存されます。これには、たとえば PHP を使用して、すべてのリクエストを評価する必要があります。

于 2010-04-11T13:37:36.383 に答える
26

回避策

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 を返すサイト上のパスに置き換えます。

于 2012-10-12T20:02:26.510 に答える
13

回避策(クリーンでナイスな(または機能している!コメントを参照)ソリューションではありません):

彼の資格情報を一度無効にします。

適切なヘッダーを送信することで、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

したがって、彼の資格情報を一度無効にするのは簡単です。

于 2009-01-16T08:15:19.193 に答える
7

問題に対する私の解決策は次のとおりです。このページの 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;
}
于 2010-02-13T16:56:09.900 に答える
7

2 つのステップで HTTP 基本認証からログアウトする

「Password protected」という名前の HTTP 基本認証レルムがあり、Bob がログインしているとします。ログアウトするには、2 つの AJAX リクエストを作成します。

  1. スクリプト /logout_step1 にアクセスします。ランダムな一時ユーザーを .htusers に追加し、そのログインとパスワードで応答します。
  2. アクセス スクリプト /logout_step2は、一時ユーザーのログインとパスワードで認証されます。スクリプトは一時ユーザーを削除し、応答に次のヘッダーを追加します。WWW-Authenticate: Basic realm="Password protected"

この時点で、ブラウザはボブの資格情報を忘れています。

于 2012-08-23T21:04:29.103 に答える
4

通常、ブラウザーがユーザーに資格情報を要求し、特定の Web サイトにそれらを提供すると、それ以上のプロンプトは表示されずに継続します。クライアント側で Cookie をクリアするさまざまな方法とは異なり、提供された認証資格情報をブラウザーに忘れさせる同様の方法を私は知りません。

于 2009-01-16T08:01:49.643 に答える
2

Trac はデフォルトで HTTP 認証も使用します。ログアウトが機能せず、修正できません:

  • これは HTTP 認証スキーム自体の問題であり、Trac で適切に修正することはできません。
  • 現在、すべての主要なブラウザーで機能する回避策 (JavaScript またはその他) はありません。

送信元: http://trac.edgewall.org/ticket/791#comment:103

この問題は 7 年前に報告されており、HTTP はステートレスです。要求が認証資格情報を使用して行われるかどうか。しかし、それはリクエストを受信するサーバーではなく、リクエストを送信するクライアントの問題です。サーバーは、リクエスト URI に承認が必要かどうかしか判断できません。

于 2011-08-06T18:05:28.723 に答える
2

.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は、他のブラウザのように認証をクリアしません;)

インストール済みのブラウザーでテストしたところ、一度閉じると、各ブラウザーは再入力時に一貫して再認証が必要なようです。

于 2011-12-07T07:00:52.460 に答える
1

多分私は要点を逃しています。

HTTP認証を終了するために私が見つけた最も信頼できる方法は、ブラウザーとすべてのブラウザーウィンドウを閉じることです。Javascriptを使用してブラウザウィンドウを閉じることはできますが、すべてのブラウザウィンドウを閉じることができるとは思いません。

于 2012-08-23T23:24:36.213 に答える
1

これまでに見つけた最良の解決策は次のとおりです(これは一種の疑似コードであり、$isLoggedInhttp認証の疑似変数です):

「ログアウト」時に、ユーザーが実際にログアウトしたことを示す情報をセッションに保存するだけです。

function logout()
{
  //$isLoggedIn = false; //This does not work (point of this question)
  $_SESSION['logout'] = true;
}

認証を確認する場所で、条件を展開します。

function isLoggedIn()
{
  return $isLoggedIn && !$_SESSION['logout'];
}

セッションは http 認証の状態に多少関連しているため、ユーザーがブラウザを開いたままにし、http 認証がブラウザで持続している限り、ユーザーはログアウトしたままになります。

于 2009-03-03T21:25:06.117 に答える
1

私の知る限り、htaccess (つまり HTTP ベースの) 認証を使用する場合、「ログアウト」機能を実装するクリーンな方法はありません。

これは、このような認証では HTTP エラー コード '401' を使用して、資格情報が必要であることをブラウザーに伝えるためです。この時点で、ブラウザーはユーザーに詳細を求めるプロンプトを表示します。それ以降、ブラウザーが閉じられるまで、それ以上のプロンプトを表示することなく、常に資格情報が送信されます。

于 2009-01-16T08:03:37.953 に答える
0

他の人は基本的なhttp認証からログアウトすることは不可能であると言っているのは正しいですが、同様に動作する認証を実装する方法があります。明らかなアプローチの1つは、auth_memcookieを使用することです。これを使用して基本HTTP認証を本当に実装したい場合(つまり、HTTPフォームではなくブラウザダイアログを使用してログインする場合)-認証を、ユーザーが後に来た場所にリダイレクトするPHPスクリプトを含む別の.htaccess保護ディレクトリに設定するだけですmemcacheセッションを作成します。

于 2011-08-01T13:03:57.580 に答える
0

解決策を記事 ( https://www.hattonwebsolutions.co.uk/articles/how_to_logout_of_http_sessions ) にまとめましたが、ajax 呼び出しと 2x htaccess ファイルを使用しました (この質問で提案されているように: HTTP 認証からログアウトする方法) 。 (htaccess) は Google Chrome で動作しますか? )。

要するに - あなた:

  1. 同じAuthNameでhtaccessファイルを含むサブフォルダーを作成しますが、別のユーザーが必要です
  2. (間違ったユーザー名で)ページに ajax リクエストを送信し(失敗します)、ログアウトしたページへのタイムアウト リダイレクトをトリガーします。

これにより、別のユーザー名を要求する (ユーザーを混乱させる) ログアウト フォルダーに 2 番目のポップアップが表示されるのを回避できます。私の記事では Jquery を使用していますが、これを回避できるはずです。

于 2020-08-20T13:22:58.947 に答える