背景
ローカルで開発中にjavascriptで同じディレクトリの画像を読み込もうとしたらエラーが出た。
原因を調べるとどうやら同一生成元ポリシーが理由とのことだったのでこれを機に調べてみた。
同一生成元ポリシーとは?
同一オリジンポリシーは重要なセキュリティの仕組みであり、あるオリジンによって読み込まれた文書やスクリプトが、他のオリジンにあるリソースにアクセスできる方法を制限するものです。
引用元:同一オリジンポリシー
つまりあるプログラムから参照できるリソース(画像など)を制限しているという事だと思う。
それでは制限の基準にしているらしい「オリジン」とは何か。
オリジンとは?
以下の要素の組み合わせのこと
- スキーム(プロトコル)
- ホスト(ドメイン名)
- ポート番号
例えば次のURLではそれぞれ以下の箇所を意味する
http://www.example.com:80/folder/image.png
- スキーム:
http://
- ホスト:
www.example.com
- ポート番号:
80
つまりこの例では http://www.example.com:80
の部分がオリジンになる。
ポート番号がurlに含まれていない場合はなんなの?
プロトコルによって規定のポート番号が決まっており省略されている。
プロトコル | 既定のポート番号 |
---|---|
http | 80 |
https | 443 |
オリジンの一致と不一致
オリジンが一致しているかどうかについて分かりやすい例があったので以下で一部引用する。
http://store.company.com/dir/page.html
とオリジンが一致するものとしないもの
URL | 結果 | 理由 |
---|---|---|
http://store.company.com/dir2/other.html | 同一オリジン | パスだけが異なる |
http://store.company.com/dir/inner/another.html | 同一オリジン | パスだけが異なる |
https://store.company.com/page.html | 不一致 | プロトコルが異なる |
http://store.company.com:81/dir/page.html | 不一致 | ポート番号が異なる (http:// は既定で 80 番ポート) |
http://news.company.com/dir/page.html | 不一致 | ホストが異なる |
表引用元:同一オリジンポリシー
それでは改めて、同一生成元ポリシーとは?
「あるプログラムが異なるオリジンのリソースを参照できないように制限するセキュリティの仕組み」
これで納得です
疑問:なぜローカル開発中にこのエラーが出たのか
冒頭でお伝えした通り、私はローカルで開発中にこのエラーに遭遇した。
内容としてはwebGLでオブジェクトにテクスチャを張り付けるというシンプルなものだった。
index.htmlもimage.pngもアクセスする際はfileスキームを使用しているのに生成元が異なるというのがピンとこなかった。
root
∟index.html
∟script.js
∟image.png
var image = new Image();
image.src = 'image.png';
エラーが出た理由
ここ より
Modern browsers usually treat the origin of files loaded using the file:/// schema as opaque origins. What this means is that if a file includes other files from the same folder (say), they are not assumed to come from the same origin, and may trigger CORS errors.
翻訳するとこんなかんじ
現代のブラウザは通常、
file:///
スキーマを使用してロードされたファイルの起源を不透明な起源として扱う。これは、例えばあるファイルが同じフォルダから他のファイルを含む場合、それらが同じ起源から来たとは仮定されず、CORSエラーを引き起こす可能性があることを意味する。
つまりfileスキームでアクセスしたリソースは生成元不明扱いになるということ。
少なくとも私が試したchromeではこのように扱われるためエラーが出ていたことがわかった。
対策
①chromeの起動オプションで同一生成元ポリシーを無視して実行する
セキュリティリスクではあるので開発でのみ使用するべき
※何か問題が生じても当方では責任を負いかねます
②webサーバを立てる
こっちの方が無難だと思う