ホームページ  >  記事  >  ウェブフロントエンド  >  プリフライトリクエストに関する簡単な説明

プリフライトリクエストに関する簡単な説明

一个新手
一个新手オリジナル
2017-09-18 10:24:314553ブラウズ


プリフライトリクエストに関する簡単な説明

バックグラウンド

お気づきかどうかわかりませんが、バックグラウンドインターフェースを呼び出すときに、以下に示すように2回リクエストを行うことがあります

プリフライトリクエストに関する簡単な説明

実際、最初に送信するのはプリフライト リクエスト(プリフライト リクエスト)について説明します。次に、この記事では、プリフライト リクエストが送信される理由、プリフライト リクエストが送信されるタイミング、およびプリフライト リクエストの機能について説明します

1. プリフライト リクエストが送信される理由については誰もが知っています

ブラウザの同一オリジン ポリシーは、セキュリティ上の理由から、XMLHttpRequest および Fetch はすべて同一オリジン ポリシーに従うことを制限します。
ブラウザがクロスドメイン リクエストを制限するには、通常 2 つの方法があります:
1. ブラウザはクロスドメイン リクエストの開始を制限します
2. クロスドメイン リクエストは通常​​通り開始できますが、返された結果はブラウザによってインターセプトされます

一般に、ブラウザーは 2 番目のメソッドを使用して、クロスドメイン リクエストを制限します。つまり、リクエストはサーバーに到達し、データベース内のデータを操作した可能性がありますが、返された結果はブラウザーによってインターセプトされました。返された結果を取得できません。これは 1 回限りのリクエストですが、データベース内のデータに影響を与えた可能性があります。

これが起こらないようにするために、仕様では、サーバー データに副作用をもたらす可能性があるこの HTTP リクエスト メソッドについて、ブラウザはまず OPTIONS メソッドを使用してプリフライト リクエストを開始し、サーバーがクロスアクセスを許可するかどうかを学習する必要があります。ドメインリクエスト: 許可されている場合、データを含む実際のリクエストは送信されます。許可されていない場合、データを含む実際のリクエストは送信されません。

2. プリフライト リクエストを送信するタイミング

HTTP リクエストには次のものが含まれます: 単純なリクエストとプリフライトを必要とするリクエスト

1. 単純なリクエスト

単純なリクエストは CORS プリフライト リクエストをトリガーしません。 「単一リクエスト」という用語は、フェッチ仕様 (CORS が定義されている) には属しません。
以下の条件がすべて満たされる場合、リクエストは「単純なリクエスト」とみなされます。 - 次のいずれかの方法を使用します:
-

- GET
- HEAD
- POST: (POST メソッドの Content-Type 値が次のいずれかに等しい場合のみ、単純な要件とみなされます)
- - WebKit NightlyとSafari Technology Previewは、AcceptContent-Type、Accept-Language
、およびコンテンツランゲージヘッダーフィールドの値に追加の制限を追加しました。これらのヘッダー フィールドの値が「非標準」である場合、WebKit/Safari はこれらのリクエストを「単純なリクエスト」として扱いません。 WebKit/Safari のドキュメントにはどの値が「非標準」であるかが記載されていませんが、ここで議論を見つけることができます: 非標準の CORS セーフリスト要求ヘッダーの Accept、Accept-Language、および Content-Language にはプリフライトが必要です。単純な CORS の Accept、Accept-Language、および Content-Language リクエスト ヘッダーでカンマを許可し、単純な CORS リクエストの制限された Accept ヘッダーについてはブラックリスト モデルに切り替えます。他のブラウザでは、これらの追加の制限は仕様の一部ではないため、サポートされていません。 text/plain
2. プリフライトが必要なリクエスト multipart/form-data
「プリフライトが必要なリクエスト」では、サーバーが実際のリクエストを許可するかどうかを知るために、まず application/x-www-form-urlencoded

注意: WebKit Nightly 和 Safari Technology Preview 为Accept
, Accept-Language
, 和 Content-Language
首部字段的值添加了额外的限制。如果这些首部字段的值是“非标准”的,WebKit/Safari 就不会将这些请求视为“简单请求”。WebKit/Safari 并没有在文档中列出哪些值是“非标准”的,不过我们可以在这里找到相关讨论:Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language, Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS, and Switch to a blacklist model for restricted Accept headers in simple CORS requests。其它浏览器并不支持这些额外的限制,因为它们不属于规范的一部分。

2.需预检的请求

“需预检的请求”要求必须首先使用OPTIONS メソッドを使用してサービス エリアへのプリフライト リクエストを開始する必要があります。 「プリフライト リクエスト」を使用すると、クロスドメイン リクエストがサーバー上のユーザー データに予期せぬ影響を与えることを回避できます。

リクエストが次の条件のいずれかを満たしている場合、最初にプリフライトリクエストを送信する必要があります:
- 次の HTTP メソッドのいずれかを使用します:
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
- CORS にとって安全なヘッダー フィールドのセット以外のヘッダー フィールドを人為的に設定します。コレクションは次のとおりです:
- Accept
- Accept-Language
- Content-Language
- Content-Type
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type の値は次のいずれでもありません:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain

以下は、プリフライト リクエストを実行する必要がある HTTP リクエストです:

var invocation = new XMLHttpRequest();
var url = ' 
var body = &#39;<?xml version="1.0"?><person><name>Arun</name></person>&#39;;function callOtherDomain(){
  if(invocation)
    {
      invocation.open(&#39;POST&#39;, url, true);
      invocation.setRequestHeader(&#39;X-PRODUCT&#39;, &#39;H5&#39;);
      invocation.setRequestHeader(&#39;Content-Type&#39;, &#39;application/xml&#39;);
      invocation.onreadystatechange = handler;
      invocation.send(body); 
    }
}
......

上記のコードは、POST リクエストを使用して、カスタム ヘッダー フィールド (X-PRODUCT:H5) を含む XML ドキュメントを送信します。さらに、リクエストの Content-Typeapplication/xml です。したがって、リクエストは最初に「プリフライトリクエスト」を開始する必要があります。
プリフライトリクエストに関する簡単な説明Content-Typeapplication/xml。因此,该请求需要首先发起“预检请求”。
プリフライトリクエストに関する簡単な説明

1. OPTIONS /resources/post-here/ 
2. HTTP/1.13. Host: bar.other4. User-Agent: Mozilla/5.0 (Macintosh; U; 5.Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre6. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.87. Accept-Language: en-us,en;q=0.58. Accept-Encoding: gzip,deflate9. Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.710. Connection: keep-alive11. Origin: http://foo.example12. Access-Control-Request-Method: POST13. Access-Control-Request-Headers: X-PINGOTHER, Content-Type14. HTTP/1.1 200 OK15. Date: Mon, 01 Dec 2008 01:15:39 GMT16. Server: Apache/2.0.61 (Unix)17. Access-Control-Allow-Origin: http://foo.example18. Access-Control-Allow-Methods: POST, GET, OPTIONS19. Access-Control-Allow-Headers: X-PINGOTHER, Content-Type20. Access-Control-Max-Age: 8640021. Vary: Accept-Encoding, Origin22. Content-Encoding: gzip23. Content-Length: 024. Keep-Alive: timeout=2, max=10025. Connection: Keep-Alive26. Content-Type: text/plain

从上面的报文中可以看到,第1~12行发送了一个使用OPTIONS方法的预检请求。 OPTIONS是HTTP/1.1协议中定义的方法,用以从服务器获取更多信息。该方法不会对服务器资源产生影响。遇见请求中同时携带了下面两个首部字段:

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PRODUCT

首部字段 Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法。首部字段 Access-Control-Request-Headers 告知服务器,实际请求将携带两个自定义请求首部字段:X-PINGOTHER 与 Content-Type。服务器据此决定,该实际请求是否被允许。

第14~26行 为预检请求的响应,表明服务器将坚守后续的实际请求。重点看第17~20行:

Access-Control-Allow-Origin: http://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-TypeAccess-Control-Max-Age: 86400

首部字段 Access-Control-Allow-Methods 表明服务器允许客户端使用 POST,GET 和 OPTIONS 方法发起请求。

首部字段Access-Control-Allow-Headers 表明服务器允许请求中携带字段X-PINGOTHERContent-Type。与 Access-Control-Allow-Methods一样,Access-Control-Allow-Headers的值为逗号分割的列表。

最后,首部字段

Access-Control-Max-Age

POST /resources/post-here/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3preAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7Connection: keep-aliveX-PINGOTHER: pingpongContent-Type: text/xml; charset=UTF-8Referer: http://foo.example/examples/preflightInvocation.htmlContent-Length: 55Origin: http://foo.examplePragma: no-cacheCache-Control: no-cache<?xml version="1.0"?><person><name>Arun</name></person>HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain
[Some GZIP&#39;d payload]

上記のメッセージからわかるように、1 行目から 12 行目は、OPTIONS メソッドを使用してプリフライト リクエストを送信します。 OPTIONS は、サーバーから詳細情報を取得するために HTTP/1.1 プロトコルで定義されたメソッドです。この方法はサーバーのリソースには影響しません。リクエストには、次の 2 つのヘッダー フィールドが同時に含まれています:

rrreee

ヘッダー フィールド Access-Control-Request-Method は、実際のリクエストが POST メソッドを使用することをサーバーに伝えます。ヘッダー フィールド Access-Control-Request-Headers は、実際のリクエストに 2 つのカスタム リクエスト ヘッダー フィールド (X-PINGOTHER と Content-Type) が含まれることをサーバーに伝えます。サーバーはこれに基づいて、実際のリクエストが許可されるかどうかを決定します。 🎜🎜行 14 ~ 26 はプリフライト リクエストに対する応答で、サーバーが後続の実際のリクエストに固執することを示しています。 17 ~ 20 行目に注目してください: 🎜rrreee🎜 ヘッダー フィールド Access-Control-Allow-Methods は、サーバーがクライアントに POST、GET、および OPTIONS メソッドを使用してリクエストを開始することを許可していることを示します。 🎜🎜ヘッダー フィールド Access-Control-Allow-Headers は、サーバーがフィールド X-PINGOTHERContent-Type の伝送を許可することを示しますリクエストの中で。 Access-Control-Allow-Methods と同様、Access-Control-Allow-Headers の値はカンマ区切りのリストです。 🎜🎜最後に、ヘッダー フィールド 🎜🎜Access-Control-Max-Age は、応答が 86400 秒、つまり 24 時間有効であることを示しています。有効期間内であれば、ブラウザは同じリクエストに対して再度プリフライト リクエストを開始する必要はありません。ブラウザ自体が最大有効時間を保持しているため、このヘッダー フィールドの値が最大有効時間を超えると有効になりません。 🎜🎜プリフライトリクエストが完了したら、実際のリクエストを送信します: 🎜rrreee

以上がプリフライトリクエストに関する簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。