h3pei.tech
お仕事のご依頼
2018-01-06

SOP(Same Origin Policy)とCORS(Cross Origin Resource Sharing)について調べた

SOP(Same Origin Policy)の理解が怪しいなぁと思ったのでちゃんとした仕様を調べた。
同時に CORS(Cross Origin Resource Sharing)についても調べることになったのでまとめて整理した。

SOP(Same Origin Policy: 同一生成元ポリシー)

  • Web ブラウザなどのセキュリティ機能の1つ
  • ある オリジン から読み込まれた文書やスクリプトについて、そのリソースから他の オリジン のリソースにアクセスできないように制限するもの

※ 参考:https://developer.mozilla.org/ja/docs/Web/Security/Same-origin_policy

オリジンとは

スキーム、ポート、ホストがそれぞれ等しいものが、同じオリジンと見なされる http://domain-a.com/dir/page.html をベースとした場合、次のようになる。

(o) http://domain-a.com/dir2/other.html
(o) http://domain-a.com/dir/inner/another.html
(x) https://domain-a.com/secure.html
-> スキームが異なる
(x) http://domain-a.com:81/dir/etc.html
-> ポートが異なる
(x) http://domain-b.com/dir/other.html
-> ホストが異なる

※ 補足

  • IP アドレスは見ていない
  • パスが異なるだけのものは問題ない

※ 参考:https://developer.mozilla.org/ja/docs/Web/Security/Same-origin_policy#Definition_of_an_origin

制限されるもの

  • XMLHTTPRequest による取得
  • スクリプトによる別のオリジンである iframewindow に対する操作
  • Canvas への一部の操作

制限されないもの

SOP(同一生成元ポリシー)には許されているものがいくつかある。 以下、異なるオリジンに埋め込むことができるリソースの例。

  • <script src="..."></script> による JavaScript
  • <link rel="stylesheet" href="..."> による CSS
  • <img> による画像
  • <video>, <audio> によるメディアファイル
  • <object>, <embed>, <applet> によるプラグイン
  • @font-face で指定されたフォント
  • <frame>, <iframe> に関連する様々なもの
  • <form> からの送信

異なるオリジンへのアクセスを許可する方法

  • かつては JSONP という手法が使われていた(JSONP については省略)
  • 現在では CORS を使用することが推奨されているようだ

CORS (Cross Origin Resource Sharing)

  • SOP はセキュリティ上重要な仕組みだが、まっとうな Web アプリケーション開発者にとってはオリジンをまたいだアクセスが必要になるケースが多かった。そこで CORS が登場した
  • Web サーバがドメインをまたぐアクセスを制御する方法を規定することで、ドメイン間の安全な通信を保証する
  • つまり、CORS の仕様に則れば、ドメインをまたいだアクセス(クロスオリジン HTTP リクエスト)ができるようになる

※ 参考:https://developer.mozilla.org/ja/docs/Web/HTTP/HTTP_access_control#Overview

CORS のパターン

大きく2つのパターンがある

  • (1) simple cross-origin request
  • (2) actual request(プリフライトがある)

simple cross-origin request になる条件は以下の通り

  • HTTP メソッドが GET,POST,HEAD のいずれかである
  • Header が Accept,Accept-Language, Content-Language, Content-Type 以外を含まない
  • Content-Type を含む場合、その値が application/x-www-form-urlencoded, multipart/form-data, text-plain のいずれかである

上記の条件に合致しない場合は actual request というプリフライトが必要なパターンになる

※ 参考:『Real World HTTP』10章

プリフライトリクエストとは

  • 実際の通信の前に、権限確認目的で送信するリクエストのこと
  • プリフライトリクエストは HTTP メソッドの OPTIONS を使って送信される
  • リクエストには以下のヘッダを含む
    • Access-Control-Request-Method: 通信を許可してもらいたいメソッド
    • Access-Control-Request-Headers: 許可して欲しいヘッダー(カンマ区切り)
    • Origin: 通信元のウェブページのドメイン名
  • プリフライトリクエストは、リクエスト前に毎回送信されるわけではない。通信内容を一定期間キャッシュすることができる。キャッシュ期間を制御するには以下のヘッダを使う
    • Access-Control-Max-Age

※ 参考:『Real World HTTP』10章

h3pei's icon

h3pei

フリーランスのソフトウェアエンジニア。Ruby / Rails アプリケーションの開発が得意領域。設計・実装・運用まで含めてプロダクト開発が好きです。

Questalという目標達成コミュニティサービスを開発しました。仲間と一緒に目標達成に取り組みたい方はぜひご利用ください。

お仕事のご依頼
GitHubnoteX