web-dev-qa-db-ja.com

401 Unauthorized AND redirect(with Location)を送信することはできますか?

401 Unauthorizedを送信し、クライアントをどこかにリダイレクトしたいと思います。しかしながら:

このようにすると:

header('HTTP/1.1 401 Unauthorized');
header('Location: /');

サーバーは302 FoundではなくLocationとともに401 Unauthorizedを送信します。

このようにすると:

header('Location: /');
header('HTTP/1.1 401 Unauthorized');

ブラウザは401 UnauthorizedLocationの両方を受け取りますが、リダイレクトはしません。

(IE 9とChrome 16は同じように動作するため、正しいと思います)

たぶん私はHTTPを誤用していますか?私のアプリのインターフェースは、すべてのクライアントでまったく同じにしたいです:テキストブラウザ、最新のブラウザ、APIコールなど。401+応答テキストはAPIユーザーに何を伝えるでしょう。リダイレクトはブラウザに役立ちます。

(良い)方法はありますか?

35
Rudie

定義により( RFC 2616 を参照)、HTTP 302応答コードisはリダイレクトコードです。これがないと、ロケーションヘッダーが無視される場合があります。

ただし、HTTP 401応答し、出力を表示します。ユーザーをエラーページにリダイレクトする代わりに、同じリクエストでHTTP本文に送信するコンテンツを単純に書き込むことができます。

27
David Chan

私はここに非常に遅れて入りますが、2セントを追加すると思いました。私が理解しているように、ユーザーが正しい承認を持っていないことを示し、ログインするように促すことを望んでいます。 in)、またログインページに転送します-しかし、これは達成するのが非常に簡単ではなく、ほとんどのライブラリですぐにサポートされていません。 1つの解決策は、別の回答で提案されているように、401応答の本文にログインページを表示することです。ただし、確立/ベストプラクティスの観点からこれを見てみましょう。

テストケース1:Facebook

ログアウト中に保護されたFacebookページ(ユーザープロファイル)に移動すると、404 Not Found応答が返されます。 Facebookは汎用の「このページは利用できません」ページを提供します。このページにはログインフォームも含まれています。面白い。さらに興味深いのは、「イベント」ページに移動すると、ログインページに転送する302応答を提供することです(200応答を返します)。だから私たちはknowが存在するページに対して302を返すが、存在するかもしれないページ(例えば保護するために404ユーザーのプライバシー)。

テストケース2:Google Inbox

ログアウトしているときに受信ボックスに移動すると302が返され、Facebookのようなログインページに転送されます。 Google+プロフィールを非公開にする方法がわからなかったため、テストデータはありません...

テストケース3:Amazon.com

ログアウトしたときに注文履歴に移動すると、302が返され、以前と同じようにログインページに転送されます。 Amazonには「プロファイル」ページの概念がないため、ここでもテストできません。

ここでテストケースを要約すると、ユーザーがログインする必要がある場合は302 Foundを返してログインページに転送するのがベストプラクティスのようです(ただし、303 See Seeが実際により適切であると主張しますが)。もちろん、これは実際の人間のユーザーがユーザー名とパスワードをhtml形式で入力する必要がある場合だけです。他のタイプの認証(基本、APIキーなど)の場合、401 Unauthorizedが適切な応答であることは明らかです。この場合、ログインページに転送する必要はありません。

12
tytk

3xxはリダイレクトを意味します
4xxは、ブラウザが何か間違ったことをしたことを意味します。

コードがそのまま分割される理由があります-それらは混同しない;)

5

KolinkとDavid(+1)からのすばらしい回答に加えて、401を返し、ブラウザにリダイレクトするように指示することで、HTTPプロトコルのセマンティクスを変更しようとしていることを指摘します。これはHTTPプロトコルの動作方法ではありません。その結果を得る方法を見つけた場合、HTTPクライアントはサービスの動作が非標準であると判断します。

401を送信してブラウザーで処理できるようにするか、状況を異なる方法で処理します(たとえば、あるコメンターが提案したように、ログインページにリダイレクトするか、ユーザーがアクセスできない理由を説明するページにリダイレクトするなど)。

4
Eric J.

きれいな方法は次のとおりです。

401ページでは、リクエストの「accept」ヘッダーに基づいて送信する「view」を選択できます。

受け入れがapplication/jsonの場合、本文を含めることができます。

{"status":401;"message":"Authentication required"}

「受け入れ」がtext/htmlの場合、本文を含めることができます。

<form action="/signin" method="post">
    <!-- bla bla -->
    <input type="hidden" name="redirect" value="[URL ENCODE REQUEST URI]">
</form>

次に、同じ質問にぶつかります...ログインに成功すると200 OKまたは302 Foundを発行しますか? (私がそこで行ったことを参照してください?)

任意のページで認証を処理できる場合、フォームアクションを同じページURLにするだけでかまいませんが、XSSに注意ユーザーが指定したrequest_uriをフォームアクション属性に入れる場合。

3
Frank Forte

401を送信してから、応答本文でwindow.location = 'domain.com'を送信できます。ただし、ユーザーは401が発生したことを知らずにすぐにリダイレクトされます。

1
rkosegi

WebブラウザはRESTクライアントではありません。位置ヘッダーと本文コンテンツのない送信ステータス200に固執します。30xリダイレクトは、移動したページ用です。 Webブラウザでリダイレクトします。

または、Webサーバーに構成可能なエラーページがある場合があります。エラーページにjavascriptを追加してリダイレクトできます。

0
Jeff Harris