CORSについて学んだので自分なりのまとめと業務で起きたトラブルの対処について

オリジン間リソース共有 (CORS)という技術があります。
ドメインAのWebページを表示する際に、一部のコンテンツをドメインBから取得してそれを表示したいといった場合に利用する必要があります。
それは最近のWebでは割とありふれたことだと思います。
なので意識せずともかなりの頻度で利用されているのではないでしょうか。 

先日業務でCORSを意識した問題に直面してしまったこともあって、一度きちんとした技術文書を読んだ方が良いと思い、Mozillaが提供しているMDN web docsの丁寧なドキュメントを読んでみました。

CORSまとめ

  • WebブラウザがドメインAのページを取得したいが、ドメインAのそのページはドメインBのコンテンツを含むといった場合に、ドメインAのサーバはドメインBのコンテンツを取得して自ページのコンテンツの一部としてWebブラウザに返さなければいけない
  • その時に利用される技術がCORS
  • CDNで画像やスタイルシートやフォントやスクリプトを配信している昨今ではかなりの頻度で利用されていると思われる
  • 基本的にはHTTPヘッダに所定の内容をクライアントとサーバが用意することで成り立つ
  • CORSができるかどうかを確認するために「プリフライトリクエスト」という事前HTTPアクセスが必要である
  • 「プリフライトリクエスト」はOPTIONメソッドで行われる…GETやPOSTではない
  • 「プリフライトリクエスト」が発生しない「単純リクエスト」というCORSリクエストもあるが該当条件が厳しい
  • 特に世の中に多そうなcontent-typeが「text/html」のページは単純リクエスト対象外なので基本的にはほとんどのCORSでプリフライトリクエストが発生すると考えた方が良さそう
  • プリフライトリクエスト時にクライアントから発送される「Access-Control-Request-Method」にはプリフライト後の本来のリクエストでどのメソッドが使われるかが書かれている
  • 同様に「Access-Control-Request-Headers」には次に行われる本来のリクエストでどのようなヘッダが送信されるかについて書かれいる
  • プリフライトリクエストを処理するためにサーバ側(CORSで一部コンテンツを提供するドメインBのサーバ)はOPTIONメソッドを受け入れるように設定されている必要がある
  • リダイレクトを含むCORSは以下の2点で対処できるが対応できない場合も多そうなのでリダイレクトしない前提でシステム構成を検討した方が良い
    • リクエストが生成されるサーバーの制御権を持っているのであれば、サーバー側の振る舞いを変更して、プリフライトが発生しないようにするか、リダイレクトが発生しないようにする
    • リクエストをプリフライトを起こさない単純リクエストなどに変更する

業務で起こった問題とその対処

業務ではAWSのCloudFrontで静的コンテンツ配信を行なっており、自社サービスのCDNサーバ的な位置付けで利用していたりもしますが、先日CORSの上記の仕様を理解できておらずに新規構築時に問題が発生したりしました。
結論としてはプリフライトリクエストを行わせるために、CloudFront側でクライアントからのOPTIONメソッドを許可する必要があり、構築時には許可されていなかったためプリフライトリクエスト自体が失敗し、結果CORSを利用した別ドメインコンテンツ取得ができない状況になっていました。
OPTIONSを許可してあげたらアプリケーションサーバが期待通りにCDNサーバとして用意しているCloudFront(+S3)からコンテンツを取得することができました。

CloudFrontの「Allowed HTTP Methods」に「GET,HEAD,OPTIONS」という選択肢があるのはそういった理由からOPTIONを優先的に許可しなければならないパターンがあるからかなぁなどという気づきが得られました。



コメント

このブログの人気の投稿

初めてぐらいの勢いで特定のブランチにマージする業務を行ったときのメモ

指定された国のタイムゾーン情報をどうやって設定すれば良いか調べる方法

[自動化][UWSC] UWSCを使ってWebテスト・Web作業の自動化(のはじめの一歩)