web-dev-qa-db-ja.com

HTTP基本認証を使用するときにユーザーをログアウトする

ユーザーがHTTP基本認証モードでログインできるようにしたい。

問題は、私も彼らが再びログアウトできるようにしたいということです-奇妙なことに、ブラウザはそれをサポートしていないようです。

これはソーシャルハッキングのリスクと見なされます。ユーザーはマシンのロックを解除したままブラウザを開いたままにしておくと、他の誰かが簡単にサイトにアクセスできます。ブラウザタブを閉じるだけではトークンをリセットするのに十分ではないため、ユーザーが見逃しやすいことに注意してください。

だから私は回避策を考え出しましたが、それは完全な手がかりです:

1)ログオフページにリダイレクトします

2)そのページでスクリプトを起動して、ダミーの資格情報を使用して別のページをajaxロードします。

$j.ajax({
    url: '<%:Url.Action("LogOff401", new { id = random })%>',
    type: 'POST',
    username: '<%:random%>',
    password: '<%:random%>',
    success: function () { alert('logged off'); }
});

3)最初は常に401を返し(新しい資格情報を強制的に渡すため)、ダミーの資格情報のみを受け入れる必要があります。

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOff401(string id)
{
    // if we've been passed HTTP authorisation
    string httpAuth = this.Request.Headers["Authorization"];
    if (!string.IsNullOrEmpty(httpAuth) &&
        httpAuth.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
    {
        // build the string we expect - don't allow regular users to pass
        byte[] enc = Encoding.UTF8.GetBytes(id + ':' + id);
        string expected = "basic " + Convert.ToBase64String(enc);

        if (string.Equals(httpAuth, expected, StringComparison.OrdinalIgnoreCase))
        {
            return Content("You are logged out.");
        }
    }

    // return a request for an HTTP basic auth token, this will cause XmlHttp to pass the new header
    this.Response.StatusCode = 401; 
    this.Response.StatusDescription = "Unauthorized";
    this.Response.AppendHeader("WWW-Authenticate", "basic realm=\"My Realm\""); 

    return Content("Force AJAX component to sent header");
}

4)これで、ランダムな文字列の資格情報が受け入れられ、代わりにブラウザによってキャッシュされました。彼らが別のページにアクセスすると、それらを使用しようとし、失敗してから、適切なページを要求します。

私のコード例ではjQueryとASP.NetMVCを使用していますが、どのテクノロジースタックでも同じことが可能であることに注意してください。

IE6以降でこれを行う別の方法があります。

document.execCommand("ClearAuthenticationCache");

ただし、これによりall認証がクリアされます-彼らは私のサイトからログアウトし、電子メールからもログアウトします。これで終わりです。

これを行うためのより良い方法はありますか?

私はこれについて その他質問 を見てきましたが、彼らは2歳です-IE9、FX4、Chromeなどで今より良い方法はありますか?

これを行うためのより良い方法がない場合、このクラッジは信頼できますか?それをより堅牢にする方法はありますか?

23
Keith

短い答えは次のとおりです。
基本認証の現在の実装を考えると、HTTP基本認証またはダイジェスト認証を使用して「ログオフ」を達成するための信頼できる手順はありません。

このような認証は、クライアントにAuthorizationヘッダーをリクエストに追加させることで機能します。
特定のリソースについて、サーバーが提供された資格情報に満足していない場合(たとえば、資格情報がない場合)、サーバーは「401 Unauthorized」ステータスコードで応答し、認証を要求します。その目的のために、応答とともにWWW-Authenticateヘッダーを提供します。

クライアントは、サーバーが認証を要求するのを待つ必要はありません。いくつかのローカルな仮定に基づいて、単にAuthorizationヘッダーを提供する場合があります(たとえば、最後に成功した試行からのキャッシュされた情報)。

認証情報を「クリア」するための概説されたアプローチは、幅広いクライアント(つまり、広範囲のブラウザ)で機能する可能性が高いですが、他のクライアントが「よりスマート」であり、適切な認証データを単に区別するという保証はまったくありません。 「ログアウト」ページおよびターゲットサイトの他のページ。

クライアント側の証明書ベースの認証を使用する場合にも、同様の「問題」が認識されます。クライアントからの明確なサポートがない限り、あなたは失われた地面で戦うかもしれません。

したがって、「ログオフ」が懸念される場合は、セッションベースの認証に移行してください。

サーバー側で認証の実装にアクセスできる場合は、Authorizationヘッダーで提示された認証情報を無視する機能を実装できる可能性があります(現在の「セッション中に提示されたものと同じ場合)」アプリケーションレベルコードの要求に応じて(または、資格情報が再要求された後に「タイムアウト」を提供する)、クライアントがユーザーに「新しい」資格情報の提供(新しいログインの実行)を要求するようにします。

4
rpy