IT web開発

クロスオリジン通信(Cross Origin)と同一成制限ポリシー(Same Origin)

2020年11月10日


オリジンBをオリジン弁当と思った方は重症ですので、病院へ行きましょう!
 

Access-Control-Allow-Origin設定。同一生成元ポリシー

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

通常iframeなどの埋め込みは
自分のサイトのものもあれば、別ドメインのものをいれたりします。
自分のサイトのiframeなら、全然問題ないが、
別サイトのiframeだとアクセスできない。まあそもそも他のサイトのものをいじれたらだめだよね。

これがいわゆる同一生成元ポリシーと呼ばれるもので、
同一生成元、つまりWebのルールとしては同一サイト(ドメイン、オリジン)で生成された(そのオリジン内の)コンテンツということ。

そのため、通常はアクセスできません。

でもアクセスしたい!

でももちろん異なるドメインへアクセスしたいというのはあるかと思います。
そのためには基本的にこちらからは何もできません。
そもそもこっちから異なるコンテンツへ勝手にアクセスしてはいけないから同一生成元ポリシーがあるのに、できるわけがないです。

なので、勝手にアクセスしてもいいよ!と許可をそのことなるドメインが許可を出したら、アクセスできるわけです。
これがいわゆるAccess-Control-Allow-Origin設定です。
これはその外部ドメイン側で設定をする必要があり、そこに指定したドメインのみ、
そのドメインからその外部ドメインへのアクセス許可が与えられます。

そのため、外部ドメインの方で設定となるのでこちらで設定はできないので、正直難しいです。

Access-Control-Allow-Origin設定

こちらから異なるドメインへアクセスするとき、いきなりリクエストをするのではなく、まずは軽いリクエストとしてプレフライトリクエストをします。
プレフライトリクエストとは、事前に3rd partyドメインへのリクエストが通るか、許可されているかを確認します。
プレ、つまり本リクエスト前のリクエストで、通常のリクエストだとHTTPリクエストヘッダなどデータ量も多いので、拒否された場合の通信料が大きいのでもったいないので、一回事前に許可されるかされないかを確認しているわけです。

そして問題なければ本リクエストを投げて、実際に処理をします。

Google等のサービス

iframeでよくある例としては、Youtubeの埋め込みがある。
あとtwitter widget
あとAjaxなど。

通常Youtubeの埋め込みをするとき、iframeタグを入れて動画の読み込みをすることができますが、
これはYoutubeという外部のドメインへリクエストをして、それでレスポンスとしてYoutubeのコンテンツを返しています。
もちろん3rd partyドメインへのリクエストなので、通常はクロスオリジンとなり、同一生成元ポリシーのルールに引っ掛かります。

しかし、Youtubeの埋め込み動画のHTTPレスポンスヘッダを見ると、
Access-Control-Allow-Origin
は*となっており、誰でもリクエストしてレスポンスを受けることを許可していることになります。

 
 
 
 
 
 
 

クロスサイトリクエストフォージェリ(CSRF)
クロスサイト→オリジンとは別サイト
リクエスト→そこに通信する
フォージェリ→偽造
つまり、普通のリクエストでAPIでデータやコンテンツを引っ張ってくるのではなく、やましい処理をするために外部サイトへリクエストするということです。
こういったものに対応するために、W3Cは同一成制限ポリシーを設けています。
 

通常通信はそのサーバのみである。これがオリジン。
しかし別のサーバに通信してコンテンツを持ってこれてしまうと、個人情報などそのサーバに入っている情報をとってこれてしまいます。
なので、そういったことができないようにする仕組みがクロスオリジン通信です。

クロスなので、現在通信している1st party domainではなく、外部の他のサーバとの通信をクロスさせないという意味ですね。
 

しかし今はYoutubeを埋め込んだり、さまざまなFormや決済システムなど、他のサーバにあるものをブラウザで表示させたりしています。
なので、そういったクロスな通信ができているのですが、クロスオリジン通信は通常はできません。
 

ではその通信はどのようにして通信ができるようになっているのでしょうか。
 

直感的にわかると思いますが、
勝手に通信されるサーバは勝手にデータとっていくなよ!コンテンツとっていくなよ!ってなるわけです。
なので、このドメインからのアクセスならコンテンツとっていってもいいよ!通信してもいいよ!って許可をするわけです。
その設定を、通信される3rd partyドメインサーバの方で行うということになります。

外部通信するようなもの

imgタグのsrc属性(サーバへの通信になるのでasyncなど指定可能)
scriptタグのsrc属性
iframeタグによるHTMLファイルの読み込み
ajaxなどの非同期処理(サーバへの通信)
Google Analyticsタグなど、GAサーバとの通信(3rd party domain)
外部のコンテンツ挿入(レコメンドエンジンなど)
さまざまな通信で自分のサーバ(オリジン)ではなく、外部サーバ内にあるコンテンツを持ってきたりします。
 

ではどのようにしてその通信を許可しているのか?

Cloud functionsで許可した場合と許可していない場合の通信エラーなどの表示を見せるか!
Cloud functionsをAPIサーバにして、ローカルというかどこか簡易的なページからリクエストをして通信ができるか?

echo "test"

オリジン 'https://yosshi-digital-site.com' からの 'https://cdn-au.onetrust.com/consent//.json' での XMLHttpRequest へのアクセスは、CORS ポリシーによってブロックされました。要求されたリソースに 'Access-Control-Allow-Origin' ヘッダーが存在しません。

あとGCSのコンテンツを引っ張ってこれるか?
https://cloud.google.com/blog/ja/products/application-development/php-comes-to-cloud-functions

https://dev.classmethod.jp/articles/cors-cross-origin-resource-sharing-cross-domain/

Access-Control-Allow-Origin
Cross-Origin-Resource-Policy
https://yamory.io/blog/about-cors/
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#:~:text=Access%2DControl%2DAllow%2DOrigin%20%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%81%AF%E3%80%81%E6%8C%87%E5%AE%9A,%E3%81%8B%E3%81%A9%E3%81%86%E3%81%8B%E3%82%92%E7%A4%BA%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

https://gihyo.jp/dev/serial/01/front-end_web/000302

CORS対策としてのプレフライトリクエスト

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

プレフライトリクエストとは、
外部ドメインへリクエストをして通信ができるか、CORSでエラーにならないかをメインのリクエストをする前に確かめる方法です。
このプレフライトリクエストは自動的にブラウザが行い、メインのリクエストは自分で作ります。

あれ?iframeの中普通に取れるけど。。

-IT, web開発

© 2024 Yosshi Labo. Powered by AFFINGER5