XMLHttpRequestはXXXを読み込めません 'Access-Control-Allow-Origin'ヘッダーがありません


111

tl; dr; 同一生成元ポリシーについて

express.jsサーバーのインスタンスを開始するGruntプロセスがあります。これは、Chromeの開発者コンソール(最新バージョン)のエラーログに次のように表示される空白ページの提供を開始するまで、まったく問題なく機能していました。

XMLHttpRequestがhttps://www.example.com/を読み込め ません。リクエストされたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。したがって、オリジン ' http:// localhost:4300 'はアクセスを許可されません。

ページにアクセスできないのはなぜですか?


私はウェブサイトに取り組んでおり、5分前は大丈夫でした。
Peter David Carter、

1
CORSヘッダーを発行しますか?おそらく、コードを共有した方が見やすいでしょう
Jaromanda X '22

おそらく。どの部署に問い合わせればよいですか?私は単にbackbone.marionetteのことをやっています...
ピーターデイビッドカーター

うん。とにかく部門の組織が常に統一されているとは限らないので、それはおそらく曖昧な質問ですが、私の会社のバックエンド/ルーティング/システム管理者のことを少し知りたいのですが、これは慣れるのに良い言い訳のように思えました私自身なので、将来問題が発生した場合は、私がお手伝いできます。
Peter David Carter

私はあなたの操作の中でサーバー側の誰かに尋ねます。以前にアクセスできた場合は、変更されているはずです。
Larry Lane

回答:


204

tl; dr —関連する部分を見つけやすくするために、回答の最後に見出しと見出しがあります。すべてを読むことをお勧めしますが、さまざまな状況でどのように適用されるかを簡単に理解できるようにする理由を理解するのに役立つ背景が提供されるためです。

同一生成元ポリシーについて

これは同一生成元ポリシーです。これは、ブラウザによって実装されるセキュリティ機能です。

あなたの特定のケースは、それがXMLHttpRequestにどのように実装されているかを示しています(そして、フェッチを使用すると同じ結果が得られます)だけでなく、他のものにも適用されます(に読み込まれた画像<canvas>やに読み込まれたドキュメントなど<iframe>)。わずかに異なる実装。

(奇妙なことに、それはCSSフォントにも適用されますが、それは、ファウンドファウンドリがDRMを主張し、Same Origin Policyが通常カバーするセキュリティ問題のためではないためです)。

SOPの必要性を示す標準的なシナリオは、3つのキャラクターで示すことができます。

  • アリスはウェブブラウザを持っている人です
  • ボブはウェブサイトを運営しています(https://www.[website].com/あなたの例では)
  • マロリーhttp://localhost:4300はあなたの例でウェブサイトを運営します

アリスはボブのサイトにログインしており、そこにいくつかの機密データがあります。おそらく、会社のイントラネット(LAN上のブラウザーにのみアクセス可能)、または彼女のオンラインバンキング(ユーザー名とパスワードを入力した後に取得したCookieを使用してのみアクセス可能)でしょう。

アリスは、アリスのブラウザにボブのウェブサイトへのHTTPリクエスト(彼女のIPアドレスからクッキーなど)を実行させるJavaScriptを含むマロリーのウェブサイトを訪問します。これは使用するのと同じくらい簡単かもしれませんXMLHttpRequestresponseTextです。

ブラウザの同一生成元ポリシーにより、ボブのWebサイトから返されたデータ(ボブとアリスがマロリーにアクセスさせたくない)がJavaScriptで読み取られなくなります。(たとえば、画像<img>のコンテンツがJavaScript(またはマロリー)に公開されていないため、要素全体を使用して画像を表示できることに注意してください。キャンバスをミックスにスローしない限り、同じオリジン生成します。違反エラー)。


なぜ同じ起源のポリシーが適用されないと思われるときに適用されるのか

特定のURLでは、SOPが不要な場合があります。これが当てはまるいくつかの一般的なシナリオは次のとおりです。

  • アリス、ボブ、マロリーは同じ人物です。
  • ボブは完全に公開情報を提供しています

…しかし、ブラウザは上記のいずれかが真であるかどうかを知る方法がないため、信頼は自動的ではなく、SOPが適用されます。ブラウザーが別のWebサイトに与えられたデータを提供する前に、明示的に許可を与える必要があります。


同一生成元ポリシーがWebページのJavaScriptにのみ適用される理由

ブラウザ拡張機能*、ブラウザ開発者ツールの[ネットワーク]タブ、Postmanなどのアプリケーションは、インストールされたソフトウェアです。あるWebサイトから別のWebサイトにアクセスしたため、別のWebサイトに属するJavaScriptにデータを渡していない。ソフトウェアのインストールは通常、より意識的な選択を行います。

リスクがあると考えられる第三者(Mallory)は存在しません。

*ブラウザーの拡張機能は、クロスオリジンの問題を回避するために慎重に作成する必要があります。例については、Chromeのドキュメントを参照してください


JSを使用せずにページにデータを表示できる理由

マロリーのサイトがブラウザにサードパーティからデータをフェッチして表示できる状況がいくつかあります(たとえば<img>、画像を表示する要素を追加することによって)。ただし、MalloryのJavaScriptがそのリソースのデータを読み取ることはできません。これを行うことができるのは、AliceのブラウザーとBobのサーバーだけなので、依然として安全です。


CORS

Access-Control-Allow-OriginHTTPの応答エラーメッセージで参照さヘッダはの一部であるCORSボブが明示的にアリスのブラウザを介してアクセスするマロリーのサイトへのデータのアクセス許可を付与することを可能にする標準。

基本的な実装には、次のものが含まれます。

Access-Control-Allow-Origin: *

…応答ヘッダーで、任意のWebサイトがデータを読み取ることを許可します。

Access-Control-Allow-Origin: http://example.com/

…特定のサイトのみにアクセスを許可し、ボブはリクエストに基づいて動的に生成できますOrigin ヘッダーにすべてではなく複数のサイトにアクセスを許可できます。

Bobがその応答ヘッダーを設定する方法の詳細は、BobのHTTPサーバーまたはサーバー側プログラミング言語、あるいはその両方によって異なります。あり、様々な一般的な構成のためのガイドのコレクションそのかもしれないのヘルプが。

CORSルールが適用される場所のモデル

注意:一部のリクエストは複雑で、ブラウザがJSの要求するGET / POST / PUT / Whateverリクエストを送信するにサーバーが応答する必要があるプリフライト OPTIONSリクエストを送信します。Access-Control-Allow-Origin特定のURLにのみ追加するCORSの実装は、多くの場合、これによって作動します。


CORSを介してアクセス許可を付与することは、ボブが次のいずれかの場合にのみ行うことです。

  • データは非公開ではありませんでした
  • マロリーは信頼された

しかし、私はボブではありません!

マロリーがこのヘッダーを追加するための標準的なメカニズムはありません。ボブのWebサイトから取得する必要があるためです。

BobがパブリックAPIを実行している場合は、CORSをオンにするメカニズムが存在する可能性があります(おそらく、リクエストを特定の方法でフォーマットするか、Bobのサイトの開発者ポータルサイトにログインした後で構成オプションを使用します)。ただし、これはボブが実装するメカニズムでなければなりません。マロリーは、ボブのサイトにあるドキュメントを読んで何か入手できるかどうかを確認したり、ボブと話し合ってCORSの実装を依頼したりできます。


「プリフライトへの対応」に関するエラーメッセージ

一部のクロスオリジンリクエストはプリフライトされています。

これは、(大まかに言えば)次のようなクロスオリジン要求を行おうとすると発生します。

  • Cookieなどの資格情報が含まれています
  • 通常のHTMLフォームでは生成できませんでした(たとえば、フォームので使用できないカスタムヘッダーまたはContent-Typeがありますenctype)。

プリフライトが必要なことを正しく行っている場合

これらの場合でも、この回答の残りの部分は引き続き適用されますが、サーバーがプリフライトリクエストをリッスンできることを確認する必要があります(これはOPTIONS(ではなく)GETPOSTまたは送信しようとしていたものは何でも)、適切に応答します。Access-Control-Allow-OriginヘッダーだけでなくAccess-Control-Allow-MethodsAccess-Control-Allow-Headers特定のHTTPメソッドやヘッダを許可します。

誤ってプリフライトをトリガーしている場合

Ajaxリクエストを作成しようとするときに、人は時々間違いを犯し、時にはそれがプリフライトの必要性を引き起こします。APIがクロスオリジンリクエストを許可するように設計されているが、プリフライトを必要とするものを何も必要としない場合、これはアクセスを破壊する可能性があります。

これを引き起こす一般的な間違いは次のとおりです。

  • 入れよう Access-Control-Allow-Originリクエストに他のCORS応答ヘッダーをます。これらはリクエストに属しておらず、役立つことは何もせず(自分に権限を付与できる権限システムのポイントは何ですか?)、応答にのみ表示される必要があります。
  • Content-Type: application/json内容を説明するリクエストボディのないGETリクエストにヘッダーを付けようとしている(通常、作成者がとを混同Content-Typeしている場合Accept)。

これらのいずれの場合でも、追加のリクエストヘッダーを削除するだけでプリフライトが不要になることがよくあります(これにより、シンプルリクエストをサポートするがプリフライトリクエストをサポートしないAPIと通信するときに問題が解決します)。


不透明な反応

場合によっては、HTTPリクエストを作成する必要がありますが、応答を読み取る必要はありません。たとえば、ログメッセージをサーバーに投稿して記録する場合などです。

(ではなく)APIを使用しているfetch場合はXMLHttpRequest CORSを使用しないように構成できます。

これでは、CORSが実行する必要があることは何もできないことに注意してください。応答を読み取ることができなくなります。プリフライトが必要なリクエストを行うことはできません。

シンプルなリクエストを作成し、レスポンスを表示せず、開発者コンソールにエラーメッセージを入力しません。

その方法はfetch、CORS を使用してリクエストを作成し、そのレスポンスを表示する権限を取得していないときに表示されるChromeエラーメッセージで説明されています。

CORSポリシーによって、 ' https://example.com/'からの' ' でのフェッチへのアクセスhttps://example.netがブロックされました:Access-Control-Allow-Origin要求されたリソースに' 'ヘッダーがありません。不透明な応答でニーズが満たされる場合は、リクエストのモードを「no-cors」に設定して、CORSを無効にしてリソースをフェッチします。

したがって:

fetch("http://example.com", { mode: "no-cors" });

CORSの代替

JSONP

ボブは、JSONPのようなハックを使用してデータを提供することもできます。これは、CORSが登場する前に人々がAjaxをクロスオリジンで作成した方法です。

これは、データをマロリーのページに挿入するJavaScriptプログラムの形式でデータを提示することによって機能します。

マロリーはボブが悪意のあるコードを提供しないことを信頼する必要があります。

共通のテーマに注意してください。データを提供するサイトは、サードパーティのサイトがブラウザに送信しているデータにアクセスしても問題ないことをブラウザに伝える必要があります。

JSONPは、<script>要素を追加して、ページ内の既存の関数を呼び出すJavaScriptプログラムの形式でデータを読み込むことで機能するため、JSONを返すURLでJSONPテクニックを使用しようとすると、通常はCORBエラーで失敗します。 JavaScriptではありません。

2つのリソースを単一のオリジンに移動します

JSが実行されるHTMLドキュメントと要求されたURLが同じオリジン(同じスキーム、ホスト名、およびポートを共有する)上にある場合、それらの同じオリジンポリシーはデフォルトでアクセス許可を付与します。CORSは必要ありません。

プロキシ

マロリー、サーバー側のコードを使用してデータをフェッチすることができます(データは、通常どおり、サーバーからHTTP経由でアリスのブラウザに渡すことができます)。

次のいずれかになります。

  • CORSヘッダーを追加する
  • 応答をJSONPに変換する
  • HTMLドキュメントと同じオリジンに存在する

そのサーバー側コードは、サードパーティ(CORS Anywhereなど)によって記述およびホストされる可能性があります。これによるプライバシーの影響に注意してください。サードパーティは、サーバー全体で誰が何をプロキシするかを監視できます。

ボブはそれが起こるためにどんな許可も与える必要はないでしょう。

それはマロリーとボブの間だけなので、ここではセキュリティへの影響はありません。ボブがマロリーがアリスであると考え、マロリーにアリスとボブの間で秘密にしておくべきデータを提供する方法はありません。

その結果、マロリーはこの手法を使用して公開を読むことができますデータ。

ただし、他の誰かのWebサイトからコンテンツを取得して自分で表示することは、著作権の侵害となり、訴訟を起こす可能性があることに注意してください。

Webアプリ以外のものを書く

「同一生成元ポリシーがWebページのJavaScriptにのみ適用される理由」で説明したように、WebページにJavaScriptを記述しないことでSOPを回避できます。

JavaScriptとHTMLを使い続けることができないという意味ではありませんが、Node-WebKitやPhoneGapなどの他のメカニズムを使用して配布することができます。

ブラウザ拡張

同一生成元ポリシーが適用される前に、ブラウザ拡張が応答にCORSヘッダーを挿入する可能性があります。

これらは開発には役立ちますが、本番サイトには実用的ではありません(サイトのすべてのユーザーに、ブラウザのセキュリティ機能を無効にするブラウザ拡張機能をインストールするよう要求するのは無理です)。

また、単純なリクエストでのみ機能する傾向があります(プリフライトOPTIONSリクエストを処理するときに失敗します)。

通常、ローカル開発サーバーで適切な開発環境を用意することをお勧めします。


その他のセキュリティリスク

SOP / CORSは、個別に処理する必要があるXSSCSRF、またはSQLインジェクション攻撃を軽減しないことに注意してください。


概要

  • 他の誰かサーバーへのCORSアクセスを可能にするクライアント側のコードでできることは何もありません。
  • サーバーを制御する場合、要求は次のように行われます。CORS権限をサーバーに追加します。
  • あなたがそれを制御する人と友好的である場合:CORS権限を追加するように彼らに依頼してください。
  • 公共サービスの場合:
    • APIドキュメントを読んで、クライアント側のJavaScriptでAPIにアクセスすることについての彼らの意見を確認してください。
      • 彼らはあなたに特定のURLを使うように言うかもしれません
      • 彼らはJSONPをサポートするかもしれません
      • クライアント側コードからのクロスオリジンアクセスをまったくサポートしていない可能性があります(これは、特に各リクエストでパーソナライズされたAPIキーを渡す必要がある場合、セキュリティ上の理由で意図的な決定となる場合があります)。
    • 不要なプリフライトリクエストをトリガーしていないことを確認してください。APIは、単純なリクエストには権限を付与しますが、プリフライトされたリクエストには付与しません。
  • 上記のいずれにも当てはまらない場合:代わりにブラウザーにサーバーと通信させ、サーバーに他のサーバーからデータをフェッチして渡します。(CORSヘッダーを、ユーザーが使用できる公的にアクセス可能なリソースに添付するサードパーティのホスティングサービスもあります)。

ローカルLANでWebサーバーを実行していて、IP / URLからajaxのロードを行おうとすると、うまくいきますか?私はまだそれを試していません。私のWebサーバーがjsonデータを再取得するのはMCUになるため
Ciasto piekarz

@Ciastopiekarz —通常の同じオリジン/異なるオリジンルールが適用されます。通常のネットワークルーティングルールが適用されます。
クエンティン2016

25
cors

@クエンティン-すごい!+1!だから私が理解しなければならないのは、アリスがCORS拡張機能を使用している場合、サーバーは彼女のhttp呼び出しがJavaScriptからではなくブラウザ拡張機能からであると見なし、それを通常の同じオリジンリクエストのように処理することです。
snippetkid

@snippetkid —いいえ。通常の場合、サーバーは常に応答でCORSヘッダーを送信し、リクエストの送信元を気にしません。応答のCORSヘッダーに基づいて、JSへのデータへのアクセスを許可または拒否するのは、ブラウザーの責任です。(プリフライトリクエストに関しては、サーバー上で/ little /より複雑になります)
Quentin

3

ターゲットサーバーはクロスオリジンリクエストを許可する必要があります。エクスプレスで許可するには、httpオプションのリクエストを処理するだけです。

app.options('/url...', function(req, res, next){
   res.header('Access-Control-Allow-Origin', "*");
   res.header('Access-Control-Allow-Methods', 'POST');
   res.header("Access-Control-Allow-Headers", "accept, content-type");
   res.header("Access-Control-Max-Age", "1728000");
   return res.sendStatus(200);
});

3

これは受け入れられた回答で言及されていないので。

  • これはこの正確な質問には当てはまりませんが、その問題を検索する他の人を助けるかもしれません
  • これは、あなたがCORSエラーを防止するために、あなたのクライアントコードで行うことができるものである場合

Simple Requestsを利用できます。
「単純なリクエスト」を実行するには、リクエストがいくつかの条件を満たす必要があります。たとえばPOSTGETHEADメソッドのみを許可し、特定のヘッダーのみを許可します(ここですべての条件を確認できます)。

クライアントコードが影響を受けるヘッダー(例: "Accept")をリクエストの修正値で明示的に設定しない場合、一部のクライアントがこれらのヘッダーをいくつかの "非標準"値で自動的に設定し、サーバーがそれを受け入れないようにする可能性があります単純なリクエスト-CORSエラーが発生します。


2

これは、CORSエラーが原因で発生しています。CORSはCross Origin Resource Sharingの略です。簡単に言うと、このエラーは、別のドメインからドメイン/リソースにアクセスしようとしたときに発生します。

詳細はこちら:jqueryでのCORSエラー

これを修正するには、他のドメインにアクセスできる場合、サーバーでAccess-Control-Allow-Originを許可する必要があります。これはヘッダーに追加できます。すべてのリクエスト/ドメインまたは特定のドメインに対してこれを有効にすることができます。

クロスオリジンリソースシェアリング(CORS)POSTリクエストを機能させる方法

これらのリンクは役立つかもしれません


0

このCORSの問題は、(他の原因のために)詳細には説明されていません。

現在、この問題は別の理由で発生しています。フロントエンドで「Access-Control-Allow-Origin」ヘッダーエラーも返されます。

ちょうど私が間違ったURLをポイントしたので、このヘッダーは適切に反映されませんでした(私はそれがそうであったと思い込んでいました)。localhost(フロントエンド)->セキュアでないhttp(httpsと想定される)の呼び出し。フロントエンドからのAPIエンドポイントが正しいプロトコルを指していることを確認します。


0

Chromeコンソールでも同じエラーが発生しました。

私の問題は、のhttp://代わりにを使用してサイトにアクセスしようとしたことでしたhttps://。したがって、修正する必要はなく、を使用して同じサイトにアクセスする必要がありましたhttps


-1

ヘッダーを追加した「取得」リクエストは、「オプション」リクエストに変換されます。したがって、Corsポリシーの問題が発生します。サーバーに「オプション」リクエストを実装する必要があります。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.