web-dev-qa-db-ja.com

承認が必要なリソースのhttpステータスコードを修正する

ユーザーがログインを要求するページにユーザーがアクセスしようとした場合に返される正しいhttpステータスコードについては、多くの混乱があるようです。

では、ログインページを表示すると、基本的にどのステータスコードが送信されますか?

4xxの範囲のステータスコードを使用する必要があると確信しています。

ここではHTTP認証について話しているわけではないので、これは使用しない少なくとも1つのステータスコードです(401 Unauthorized)。

では、何を使うべきでしょうか?答え(ここでもSO)はさまざまに見えます。

回答によると here403 Forbiddenを使用する必要があります。

ただし、ステータスコードの説明は次のとおりです。

承認は役に立たず、リクエストは繰り返されるべきではありません。

まあそれは正しいもののようには見えません。承認以来助けてください。

それでは、他の答えを見てみましょう。答え here4xxの範囲をまったく使用せず、302 Foundを使用します

302 Foundステータスコードの説明:

リクエストされたリソースは一時的に別のURIに存在します。リダイレクトは時々変更される可能性があるため、クライアントは今後のリクエストに引き続きRequest-URIを使用する必要があります(SHOULD)。この応答は、Cache-ControlまたはExpiresヘッダーフィールドで示されている場合にのみキャッシュ可能です。

それも私が望んでいることではないと思います。これは、別のURIの下にある要求されたリソースではないためです。しかし、まったく別のリソース(ログインページと認証済みコンテンツページ)です。

それで私は一緒に移動して別の answer を選択しましたが、驚くべきことにさらに別の解決策がありました。

この回答は、400 Bad Requestを選択することをお勧めします。

このステータスコードの説明は次のとおりです。

不正な構文のため、サーバーはリクエストを理解できませんでした。クライアントは変更せずにリクエストを繰り返すべきではありません。

サーバーはリクエストをうまく理解したと思いますが、ユーザーが認証される前にアクセスを与えることを拒否します。

別の answer403応答は正しいと言いますが、次で終了します:

これが、セッションCookieに基づいてアクセスを拒否しようとしている公開Webサイトである場合(それが私がやっていることです)、ログインが必要であることを示す適切な本文を含む200、またはログインページへの302一時的なリダイレクトがよくあるベスト。

したがって、403は正しいですが、200または302が最高です。

おい!それが私が探しているものです:最高のソリューション。しかし、最高のものは正しいものと同じであるべきではありませんか?そして、なぜそれが最高でしょうか?

これまでこの質問に参加してくれたすべての人に感謝します:)

私はそれについてあまり心配すべきではないことを知っています。そして、この質問はもっと仮説的なものだと思います(実際にはそうではありませんが、より良いWordがないために使用しました)。

しかし、この質問はしばらくの間私を悩ませています。

そして、もし私がマネージャーであったとしたら(いつもそうであるように、クールな響きのある言葉を拾っただけです)、私は言ったでしょう:しかし、しかし、しかし、落ち着きは重要です。 :-)

したがって、上記の状況でステータスコードを使用する場合のthe right way™は何ですか(ある場合)?

tl; dr

ログインが必要なページにユーザーがアクセスしようとしたときの正しいhttpステータスコード応答は何ですか?

57
PeeHaa

ユーザー資格情報を提供していないで、APIで必要な場合は、401 - Unauthorizedを返します。それはクライアントにそうするように挑戦するでしょう。通常、この特定のシナリオについてはほとんど議論されません。

ユーザーが有効な資格情報を提供したが、それらが不十分で、要求されたリソースにアクセスする場合(おそらく、資格情報はフリーミアムアカウントのものでしたが、要求されたリソースは有料ユーザーのみのものです)、いくつかのオプションがあります一部のHTTPコード定義が緩い場合:

  1. 403 - Forbiddenを返します。これはより説明的であり、通常、 "提供された資格情報は有効でしたが、それでもアクセスを許可するのに十分ではなかった"と理解されます。
  2. 401 - Unauthorizedを返します。セキュリティについて偏執的である場合は、上記の(1)で返されたように、クライアントに追加情報を提供したくない場合があります。
  3. 401または403のいずれかを返しますが、アクセスが拒否された理由を説明する有用な情報をレスポンス本文に含めます。繰り返しになりますが、その情報は、攻撃者に多少役立つ場合に備えて、あなたが提供したい情報よりも多くなる可能性があります。

個人的には、有効な認証情報が渡されたが、それらに関連付けられているアカウントがリクエストされたリソースにアクセスできないシナリオでは、常に#1を使用してきました。

45
Brian Kelly

次に、「最良の」、「正しい方法」、「正しい」を求めます。これらの基準は必ずしも交換可能ではなく、実際には矛盾する可能性があるため、この質問への回答は難しくなります。特にRESTfulnessが関係している場合。

「最良の」答えは、アプリケーションによって異なります。プレーンオールドブラウザーベース(POBB)Webアプリケーションを構築していますか?ネイティブクライアント(iOSやAndroidなど)を構築していて、Web経由でサービスを利用していますか? AJAX=を頻繁に使用してWebページの更新を推進していますか?カールは対象のクライアントですか?

従来のWebアプリケーションを構築しているとしましょう。 Googleがどのように実行するかを見てみましょう(簡潔にするために出力を切り刻んでいます)。

$ curl -v http://gmail.com/
< HTTP/1.1 301 Moved Permanently
< Location: http://mail.google.com/mail/
< Content-Type: text/html; charset=UTF-8
< Content-Length: 225
< ...

Googleはまず、GMailの「真の」URLにリダイレクトします(302リダイレクトを使用)。

$ curl -v http://mail.google.com/mail/
< HTTP/1.1 302 Moved Temporarily
< Location: https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=http://mail.google.com/mail/&scc=1&ltmpl=default&ltmplcache=2
< Content-Type: text/html; charset=UTF-8
< Content-Length: 352
< ...

そして、302リダイレクトを使用して、ログインページにリダイレクトします。

$ curl -v 'https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=http://mail.google.com/mail/&scc=1&ltmpl=default&ltmplcache=2'
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< ...

ログインページ自体に200ステータスコードが配信されます!

なぜこのように?

ユーザーエクスペリエンスの観点から、ユーザーが認証されていないために表示できないページにアクセスした場合、ユーザーを(ログインによって)修正できるページに移動する必要があります。この例では、ログインページは独立していて、単なる別のページです(そのため、200が適切です)。

説明とログインページへのリンクを含む4XXページを表示できます。実際、もっとRESTfulな(= /// =)ようです。しかし、それはより悪いユーザー体験です。

わかりましたが、403のようなものが理にかなっているケースはありますか?もちろんです。

ただし、最初に、403は仕様で明確に定義されていないことに注意してください。それがどのように使用されるべきかを理解するために、あなたはそれが現場でどのように実装されているかを見る必要があります。

403は、ApacheなどのWebサーバーで一般的に使用され、ブラウザがディレクトリリスト(「/」で終わるURI)を要求したときに返されるページのステータスコードとしてIISですが、サーバーでディレクトリリストが無効になっています。この場合、403は実際には特殊な404であり、何が問題かをユーザーに知らせる以外に、ユーザーにできることは多くありません。

ただし、403を使用して、ユーザーに十分な特権がないことをユーザーに通知するサイトのアクションの例を次に示します状況を修正します(詳細は 完全な応答 を確認してください):

curl -v http://www.w3.org/Protocols/rfc2616/
< HTTP/1.1 403 Forbidden
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 1564
< ...

(余談ですが、403はTwitterのAPIなどのWebベースのAPIでも見られます。ここで、403は「リクエストは理解されましたが、拒否されました。付随するエラーメッセージで理由が説明されます。このコードは、リクエストがアップデートの制限により拒否されました。」)

ただし、改善として、ユーザーをログインページにリダイレクトリダイレクトしたり、ユーザーにリンクをたどらせたりしたくないとしましょうログインページへ。代わりに、ユーザーが表示できないページにログインフォームを表示する必要があります。認証に成功すると、ページがリロードされたときにコンテンツが表示されます。失敗すると、再度ログインフォームが表示されます。別のURLに移動することはありません。

この場合、ステータスコード403は理にかなっており、401の場合と同様です。ただし、ブラウザはユーザーに認証を求めるダイアログをポップアップ表示せず、フォームはページ自体にあります。 。

この認証へのアプローチは一般的ではありませんが、理にかなっている可能性があり、開発者が実装しようとするポップアップのjavascript-modal-to-log-inソリューションよりも私見の方が好ましいです。

それは問題に帰着します、あなたはリダイレクトしたいですか?

追加:401ステータスコードについての考え...

401ステータスコード(および関連する基本/ダイジェスト認証)には、多くのことが含まれています。これはHTTP仕様に採用されており、すべての主要なブラウザーでサポートされており、本質的にRESTfulではありません...問題は、ユーザーエクスペリエンスの観点から見ると、非常に魅力的ではありません。様式化できない、不可解なポップアップダイアログ、ログアウトのためのエレガントなソリューションの欠如などがあります。あなた(または利害関係者/クライアント)がこれらの問題(大きな場合)に耐えられる場合、それは「正しい" 解決。

26
toddsundsted

同意した。 RESTは単なるプロトコルであり、厳密なプロトコルではありません。多くのパブリックWebサービスは、このスタイルから逸脱しています。必要なものを返すようにサービスを構築できます。クライアントがどのようにリターンコードを返すかを確認してください。期待する。

個人的に、私は常に401(無許可)を使用して、非認証ユーザーがログインを必要とするリソースを要求したことを示しています。次に、クライアントアプリケーションに、ユーザーをログインに導くように要求します。

無効な資格情報でのログオン試行に応答して、400(不正な要求)を使用します。

HTTP 302(移動)は、クライアントがブラウザーであるWebアプリケーションにより適しているようです。ブラウザは通常、応答でリダイレクトアドレスに従います。これは、ユーザーをログオンページに案内するのに役立ちます。

10
EJK

ここではHTTP認証について話しているわけではないので、これは使用しない少なくとも1つのステータスコード(401 Unauthorized)です。

違う。 401は、ハイパーテキスト転送プロトコル(RFC 2616 Fieldingなど)の一部ですが、HTTP認証に限定されません。さらに、リクエストがユーザー認証を必要とすることを示す唯一のステータスコードです。

302&200コードを使用することができsomeで実装する方が簡単ですすべてではありません。そして、仕様にしたい場合は、401が唯一の正解です。

そして、403は実際に返すのに最も間違ったコードです。あなたが正しく述べたように...

承認は役に立たず、リクエストは繰り返されるべきではありません。

したがって、これは明らかに承認がオプションであることを示すのに適していません。

私は標準に固執します:401 Unauthorized

-

[〜#〜]更新[〜#〜]

もう少し情報を追加して、関連する混乱を取り除きます...

応答には、要求されたリソースに適用可能なチャレンジを含むWWW-Authenticateヘッダーフィールド(セクション14.47)を含める必要があります。

これにより401の使用が妨げられると思われる場合は、次のことを覚えておく必要があります。

「フィールド値は、Request-URIに適用可能な認証スキームとパラメーターを示す少なくとも1つのチャレンジで構成されています。」

この「認証スキームを示す」とは、他の認証スキームを選択できることを意味します。

HTTPプロトコル(RFC 2616)は、アクセス認証スキームの単純なフレームワークを定義していますが、そのフレームワークを使用する必要はありません。

つまり、通常のWWW-Authに縛られることはありません。あなたは、あなたのウェブアプリがどのようにそれを承認し、それに応じたデータをヘッダーに提供するかを示さなければなりません、それだけです。仕様によると、401を使用して、独自の認可の毒を選択できます!そして、それは、401ヘッダーと承認の実装に関して、「webapp」が実行したいことを実行できる場所です。

通常のHTTP認証スキームを使用する必要があると考えて、仕様を混乱させないでください。あなたはしません!仕様が実際に適用する唯一のもの:Webアプリの認証スキームを識別/保持し、関連するパラメーターを渡して、要求側が潜在的な認証試行を開始できるようにします。

そして、それでもわからない場合は、これらすべてをシンプルですが理解できる観点にまとめることができます。たとえば、明日新しい承認スキームを発明するつもりであれば、仕様ではそれを使用することもできます。仕様がそのような新しい承認技術の実装の実装を制限していたとしたら、それらの仕様は何年も前に変更されていたはずです。仕様は標準を定義していますが、実際には多数の潜在的な実装を制限するものではありません。

8
user1093284

「TL; DR」が「TL」バージョンと一致しません。

リクエストするために承認が必要なリソースをリクエストするための適切なレスポンスは401です。

302は適切な応答ではありません。実際、リソースは他の場所では利用できないためです。元のURLは正しかった、クライアントは単に権利を持っていなかった。リダイレクトに従うと、実際に探しているものを取得できません。リソースとは何の関係もないアドホックワークフローにドロップされます。

403は不正解です。 403は「ここからそこに到達できません」エラーです。あなたは単にこれを見ることができません、私はあなたが誰であるかを気にしません。 403と404は似ていると主張する人もいます。違いは単純に403であり、サーバーは「はい、私は持っていますが、できません」と言っていますが、404は「私はあなたが話していることについて何も知りません」と言っています。セキュリティワンクは、404が「安全」であると主張します。なぜ彼らが知る必要のないことを彼らに言うのか。

発生している問題は、RESTまたはHTTPとは関係ありません。問題は、クライアントとサーバーの間にステートフルな関係を設定しようとしています。最終的にはCookieを介して明らかになります。リソース全体-> 302->ログインページは、Webブラウザーと呼ばれるハックを使用したユーザーエクスペリエンスのすべてです。これは、たまたま在庫のある形式では、ひどいHTTPクライアントとひどいREST参加者の両方です。

HTTPには認証メカニズムがあります。 Authorizationヘッダー。汎用ブラウザでのその周りのユーザーエクスペリエンスはひどいです。したがって、誰もそれを使用しません。

したがって、適切なHTTP応答がありません(401は存在しますが、それを使用しない/使用できません)。 REST応答、RESTは通常、基礎となるプロトコルに依存します(この場合はHTTPですが、すでに取り組んでいます)。

そう。ログインページの302-> 200は、彼女が書いたすべてです。あなたがもらったもの。ブラウザーを使用していない場合、またはXHRまたは他のカスタムクライアントを介してすべてを実行した場合、これは問題になりません。 Authorizationヘッダーを使用し、HTTPプロトコルに従い、DIGESTまたはAWSが使用するスキームのようなスキームを利用して実行します。次に、適切な基準を使用して、このような質問に答えることができます。

3
Will Hartung

ご指摘のとおり、403 Forbiddenは「Authorization will help」というフレーズで明示的に定義されていますが、著者がほぼ確実にここでHTTP認証を参照していたことは注目に値します(実際、サイトで別の認証スキームを使用している場合)。確かに、ステータスコードがuserではなくuser agentへのシグナルであるとすると、そのようなコードは、現時点では正しいでしょう。エージェントが提供しようとする承認は、必要な承認プロセスでこれ以上支援されません(cf401 Unauthorized)。

ただし、その定義を403 Forbidden文字通り、おそらく不適切だと感じます。おそらく409 Conflictが適用される可能性がありますか? RFC 2616§10.4.1 で定義されているとおり:

リソースの現在の
状態と競合するため、リクエストを完了できませんでした。このコードは、ユーザーが競合を解決してリクエストを再送信できることが期待される
状況でのみ許可されます
。レスポンスの本文には、ユーザーが競合の原因を認識するのに十分な
情報を含める必要があります
。問題;ただし、これは不可能である場合があり
、必須ではありません。

実際、リソースの現在の状態との競合があります。リソースは「ロックされた」状態であり、そのような競合は、ユーザーが資格情報を提供してリクエストを再送信することによってのみ「解決」できます。本文には「ユーザーが競合の原因を認識するのに十分な情報」が含まれます(ログインしていないことが示されます)。また、実際には「ユーザーまたはユーザーエージェントが問題を解決するための十分な情報 "(つまり、ログインフォーム)。

3
eggyal

あなたの答え:

401 Unauthorized特に気にしない、またはログインページにユーザーをリダイレクトしない場合

-または-

302 Foundリソースがあったことを意味しますが、リソースに返される資格情報を提供する必要があります。これは、リダイレクトを使用する場合にのみ行い、応答の本文に適切な情報を提供するようにしてください。


その他の提案:

401 Unauthorizedは通常、認証の処理後にユーザーがアクセスできないリソースに使用されます。

403 Forbidden正直なところ、私には少しあいまいです。ファイルシステムレベルからリソースをロックダウンするときに使用します。投稿のように、「承認は役に立たない」と言っています。

400 Bad Requestは、ログインの必要性が不正な構文を表していないため不適切です。

0

失敗した認証から戻るには、401が正しいステータスコードだと思います。参照 RFC 2616 section-14.8 「サーバーで自分自身を認証することを望むユーザーエージェント-通常は、401応答」

0
Julius Depulla