回答:
2018-09-13を編集:このプレフライトリクエストと、この応答の最後にそれを回避する方法に関するいくつかの精度を追加しました。
OPTIONS
リクエストは、でpre-flight
リクエストと呼ばれるものCross-origin resource sharing (CORS)
です。
特定の状況でさまざまなオリジンにわたってリクエストを行う場合に必要です。
このプリフライト要求は、実行中の要求がサーバーによって信頼されるようにするための安全対策として、一部のブラウザーによって行われます。つまり、サーバーは、リクエストで送信されるメソッド、オリジン、ヘッダーが安全に機能することを理解しています。
サーバーは、クロスオリジンリクエストを実行しようとするときはいつでも、これらのリクエストを無視せずに処理する必要があります。
良いリソースはここで見つけることができますhttp://enable-cors.org/
これらを処理して快適にするOPTIONS
方法は、メソッドを含むパスに対して、サーバーがこのヘッダーを含む応答を送信するようにすることです。
Access-Control-Allow-Origin: *
これは、サーバーが任意の発信元からの要求に応答する用意があることをブラウザーに通知します。
サーバーにCORSサポートを追加する方法の詳細については、次のフローチャートを参照してください
http://www.html5rocks.com/static/images/cors_server_flowchart.png
2018-09-13を編集
MDN docsでOPTIONS
説明されているように、CORS リクエストは一部のケースでのみトリガーされます。
一部のリクエストはCORSプリフライトをトリガーしません。これらは、この記事では「シンプルリクエスト」と呼ばれていますが、Fetch仕様(CORSを定義)ではこの用語は使用されていません。CORSプリフライトをトリガーしないリクエスト、いわゆる「シンプルリクエスト」は、次のすべての条件を満たすリクエストです。
許可されるメソッドは次のとおりです。
- 取得する
- 頭
- 役職
ユーザーエージェントによって自動的に設定されるヘッダー(たとえば、Connection、User-Agent、またはFetch仕様で「禁止されたヘッダー名」として定義された名前を持つその他のヘッダー)とは別に、許可される唯一のヘッダー手動で設定されるのは、Fetch仕様で「CORSセーフリストに登録されたリクエストヘッダー」として定義されているものです。
- 受け入れる
- 受け入れ言語
- コンテンツ言語
- Content-Type(ただし、以下の追加要件に注意してください)
- DPR
- ダウンリンク
- 保存データ
- ビューポート幅
- 幅
Content-Typeヘッダーに許可される値は次のとおりです。
- application / x-www-form-urlencoded
- multipart / form-data
- テキスト/プレーン
リクエストで使用されるXMLHttpRequestUploadオブジェクトにイベントリスナーは登録されません。これらは、XMLHttpRequest.uploadプロパティを使用してアクセスされます。
リクエストではReadableStreamオブジェクトは使用されません。
curl
apiにaを実行すると機能するのですが、chromeから実行するとエラーが発生しますか?
Origin
をシミュレートするには、リクエストにヘッダーを追加して、リクエストが特定のホスト(yourwebsite.comなど)から送信されたかのようにシミュレートします。リクエストのHTTPメソッドOPTIONS
とAccess-Control-*
ヘッダーを設定することにより、プリフライトリクエストをシミュレートすることもできます
この問題を経験しました。以下は、この問題に対する私の結論と私の解決策です。
CORS戦略によると(それについて読むことを強くお勧めします)、必要と思われる場合は、ブラウザーにOPTIONS要求の送信を強制的に停止させることはできません。
これを回避するには2つの方法があります。
Access-Control-Max-Age
OPTIONSリクエストに設定単純なクロスサイトリクエストは、次のすべての条件を満たすリクエストです。
許可されるメソッドは次のとおりです。
ユーザーエージェント(Connection、User-Agentなど)によって自動的に設定されるヘッダーとは別に、手動で設定できるヘッダーは次のとおりです。
Content-Typeヘッダーに許可される値は次のとおりです。
単純なリクエストでは、飛行前のOPTIONSリクエストは発生しません。
Access-Control-Max-Age
OPTIONSリクエストにを設定して、有効期限が切れるまで再度権限をチェックしないようにすることができます。
Access-Control-Max-Ageは、別のプリフライト要求を送信せずにプリフライト要求への応答をキャッシュできる期間を秒単位で示します。
Access-Control-Max-Age
IS 600
によると、10分であるクロムソースコードAccess-Control-Max-Age
は常に1つのリソースに対してのみ機能しGET
ます。たとえば、URLパスが同じであるが、異なるクエリは異なるリソースとして扱われます。したがって、2番目のリソースへのリクエストはプリフライトリクエストをトリガーします。Access-Control-Max-Age
。それがここでの鍵です。過剰なプリフライトリクエストを回避するのに役立ちます。
application/json
リクエストが「単純」ではない(したがってCORSがトリガーされる)だけでは避けないでください。ブラウザはその仕事をしています。次のようなヘッダーを返すようにサーバーを設定するAccess-Control-Max-Age: 86400
と、ブラウザーはOPTIONSリクエストを24時間再送信しません。
プリフライトされたOPTIONSリクエストの実際の必要性についてこの回答を参照してください:CORS-プリフライトリクエストの導入の動機は何ですか?
OPTIONSリクエストを無効にするには、ajaxリクエストで以下の条件を満たす必要があります。
application/x-www-form-urlencoded
、multipart/form-data
またはtext/plain
リファレンス:https : //developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
application/xml
またはapplication/json
「カスタムHTTPヘッダー」ではありません。ヘッダー自体はありContent-Type
、そのヘッダーを「カスタム」と呼ぶことは誤解を招くでしょう。
デバッグコンソールを開いてDisable Cache
オプションをオンにすると、プリフライトリクエストが常に送信されます(つまり、すべてのリクエストの前に)。キャッシュを無効にしない場合、プリフライトリクエストは1回だけ送信されます(サーバーごと)
はい、オプションのリクエストを回避することは可能です。オプション要求は、データを別のドメインに送信(ポスト)するときのプリフライト要求です。これはブラウザのセキュリティ問題です。しかし、iframeトランスポート層という別のテクノロジーを使用できます。CORS構成を忘れて既製のソリューションを使用することを強くお勧めします。これはどこでも機能します。
ここを見てください: ご覧ください https //github.com/jpillora/xdomain
そして実際の例:http : //jpillora.com/xdomain/
存在する理由は理解しているが、認証なしでOPTIONS呼び出しを処理しないAPIにアクセスする必要がある開発者の場合、API所有者が適切なSPA CORSサポートを追加するか、プロキシAPIを取得するまでローカルで開発できるように、一時的な回答が必要です稼働しています。
MacのSafariとChromeでCORSを無効にできることがわかりました。
Chrome:Chromeを終了し、ターミナルを開いて次のコマンドを貼り付けます: open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir
Safari:Safariで同一生成元ポリシーを無効にする
Safariで同一生成元ポリシーを無効にする場合(私は9.1.1を持っています)、開発者メニューを有効にし、開発メニューから[クロスオリジン制限を無効にする]を選択するだけで済みます。
以前の投稿で既に述べたように、OPTIONS
リクエストは理由があります。サーバーからの応答時間が長い問題(海外接続など)がある場合は、ブラウザーにプリフライト要求をキャッシュさせることもできます。
サーバーにAccess-Control-Max-Age
ヘッダーを返信してもらい、同じエンドポイントに送信されるリクエストの場合、プリフライトリクエストはキャッシュされ、もう発生しません。
OPTIONS
リクエストがこのヘッダーでキャッシュされるという事実は、私が読んだすべてのCORSドキュメントではかなり不透明です。
このような問題を解決しました。
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && ENV == 'devel') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With');
header("HTTP/1.1 200 OK");
die();
}
開発専用です。これにより、8ミリ秒と500ミリ秒ではなく、9ミリ秒と500ミリ秒待機しています。JSアプリのプロダクションはプロダクションと同じマシン上にありOPTIONS
、開発は私のローカルでしかありません。
できませんが、JSONPを使用してCORSを回避できます。
1日半かけて同様の問題を解決しようとした後、IISに関係していることがわかりました。
私のWeb APIプロジェクトは次のように設定されました。
// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
//...
}
多くの投稿で見たように、web.config> system.webServerノードにCORS固有の構成オプションがありませんでした
global.asaxまたはコントローラーにデコレーターとしてのCORS固有のコードはありません
問題はアプリプールの設定でした。
管理パイプラインモードは、古典的(に設定した統合にそれを変更)し、アイデンティティをネットワークサービスに設定した(ApplicationPoolIdentityにそれを変更)
これらの設定を変更(およびアプリプールを更新)することで修正されました。
私にとってうまくいったのは、「github.com/gorilla/handlers」をインポートして、次のように使用することでした。
router := mux.NewRouter()
router.HandleFunc("/config", getConfig).Methods("GET")
router.HandleFunc("/config/emcServer", createEmcServers).Methods("POST")
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
originsOk := handlers.AllowedOrigins([]string{"*"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
log.Fatal(http.ListenAndServe(":" + webServicePort, handlers.CORS(originsOk, headersOk, methodsOk)(router)))
Ajax POSTリクエストを実行してJSONデータを添付するとすぐに、Chromeは以前のAllowedHeaders構成になかったContent-Typeヘッダーを常に追加します。
私が過去に使用した1つの解決策-サイトがmydomain.comにあり、foreigndomain.comにajaxリクエストを行う必要があるとしましょう
ドメインから外部ドメインへのIISリライトの構成-例
<rewrite>
<rules>
<rule name="ForeignRewrite" stopProcessing="true">
<match url="^api/v1/(.*)$" />
<action type="Rewrite" url="https://foreigndomain.com/{R:1}" />
</rule>
</rules>
</rewrite>
mydomain.comサイト-同じオリジンリクエストを作成でき、オプションリクエストは必要ありません:)
リクエストをインターセプトして適切なヘッダーを書き込むプロキシを使用している場合は解決できます。ワニスの特定のケースでは、これらがルールになります。
if (req.http.host == "CUSTOM_URL" ) {
set resp.http.Access-Control-Allow-Origin = "*";
if (req.method == "OPTIONS") {
set resp.http.Access-Control-Max-Age = "1728000";
set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, PATCH, OPTIONS";
set resp.http.Access-Control-Allow-Headers = "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since";
set resp.http.Content-Length = "0";
set resp.http.Content-Type = "text/plain charset=UTF-8";
set resp.status = 204;
}
}
おそらく解決策があります(ただし、テストしませんでした)。CSP(コンテンツセキュリティポリシー)を使用してリモートドメインを有効にすると、ブラウザーはCORS OPTIONSリクエストの検証をスキップする可能性があります。
時間があれば、テストしてこの投稿を更新します。
CSP:https : //developer.mozilla.org/fr/docs/Web/HTTP/Headers/Content-Security-Policy
CSP仕様:https : //www.w3.org/TR/CSP/