web-dev-qa-db-ja.com

プリフライトとリダイレクトを使用したCORSリクエスト:許可されていません。回避策は?

ユーザーが(トークンを使用して)認証できるようにし、同じドメイン内にリダイレクトを含むAPIを設計しています。これで、303を返すエンドポイントへの認証されていないリクエストに対して、

GET /documents/123  --> 303 redirect to `/documents/abc`
GET /documents/abc  --> 200

すべてがうまく機能します。

Authorizationヘッダーが送信されるのと同じエンドポイントに認証済みのリクエストを行いましょう。これにより、リクエストは プリフライトリクエスト になり、ブラウザはプリフライトOPTIONSリクエスト、つまり.

OPTIONS /documents/123   --> 204 (everything okay, please proceed)
GET /documents/123       --> 303 redirect to `/documents/abc`

この時点で、ブラウザはGETの実際のリソースを/documents/abcで指定する代わりに、

XMLHttpRequest cannot load http://localhost:8000/people/username/nschloe. 
The request was redirected to 'http://localhost:8000/people/YDHa-B2FhMie', 
which is disallowed for cross-Origin requests that require preflight.

この動作は 標準 に準拠しています。

7.1.5プリフライトを使用したクロスオリジンリクエスト

応答のHTTPステータスコードが2xxの範囲にない場合

ネットワークエラーの手順を適用します。

これは、リダイレクトが同じドメイン(localhost)にある場合でも、1つcannotが認証済みリソースのリダイレクトを行わないことを意味するようです。

これは本当ですか?一般的な回避策はありますか?

23
Nico Schlömer

元の標準は、CORSプリフライトが成功した後のリダイレクトを除外します。 引用§7.1.5.

これは実際のリクエストです。リクエストの作成手順を適用し、リクエストの作成中に以下のリクエストルールを遵守します。

  • 応答のHTTPステータスコードが301、302、303、307、または308の場合キャッシュとネットワークエラーの手順を適用します。

あなたの努力により(ありがとう!)、8月4日の標準は 更新 で、CORSプリフライトチェックが成功した後にリダイレクトを許可しました。

ブラウザが追いつくまで、実行可能なオプションは1つまたは以下の組み合わせのようです。

  1. 単純なリクエスト に対してのみリダイレクトを発行します。
  2. 「プロキシ」としてLocationヘッダーに独自のURLを指定して、 5リダイレクト を発行します。 305は非推奨であるため、限定的なブラウザーサポートに備えてください。
  3. 偽の「リダイレクト」を行う:
    • meta refreshおよび/またはJavascript Location変更を含むHTMLを返します。
    • iframeのソースとしてリダイレクトターゲットを持つビューポートを埋めるiframeを持つHTMLを返します。
    • ユーザーがコンテンツにアクセスするためにクリックする必要があるリンクを表示します。
15
bishop