Friction River Software

  • お問い合わせ

CakePHP5入門【補足⑤】WebAPIにおけるCORS

C菜

このWebAPIのアプリって、我が社のVPSサーバ(https://friction-river.jp)上で稼働してるじゃないですか~

B美

そうね

C菜

んで、会社のLAN内にあるWebサーバにも(ダイナミックDNSを使った)ドメイン名(https://friction-river.mydns.jp)がありますよね~?

なので、社内のWebサーバ上にWebAPIを呼び出すHTMLファイルを置いてアクセスしてみたんですよ~

A子

バッチリ動いたんだよね?

C菜

それがダメだったんですよね~(苦笑)

何度試しても「通信エラー」になっちゃいます~

B美

あぁ、実はこのWebアプリのバージョンが未だに「1.0.0」になっていないのは、そこに理由があるからなの
(注:2026年5月8日時点)

もしもブラウザがEdgeであるならば、「F12」キーを押して開発者ツールを表示してちょうだい
そのあと、コンソール(Console)を表示した状態で、HTMLファイルにアクセスしてWebAPIを呼び出してみてね

C菜

やってみました~

あれ?
なんかエラーが出ましたよ~

blocked by CORS policy」って何ですか~?

B美

それこそが今回の主題テーマである「CORS」よ

A子

ん?

なんかの略?
(英単語の頭文字をとったものっぽい)

B美

正解!
Cross-Origin Resource Sharingの頭文字を繋げたものね

オリジンをまたいで(クロスオリジン)資源(リソース)を共有する(シェアリング)仕組みよ

A子

いやいや
そもそも「オリジン」って何なのさ

C菜

もしかして「ドメイン」のことでしょうか~?

B美

うーん、惜しい!

例えば、「https://friction-river.jp」において、実は「ポート番号(443)」が省略されてるの
なので、正確には「https://friction-river.jp:443」なんだけど、これって

・通信プロトコル(スキーム):https
・ドメイン:friction-river.jp
・ポート番号:443

の組み合わせなのね
で、この全体を「オリジン」って呼ぶの

C菜

「ドメイン」は「オリジン」の一部分なんですね~

B美

そういうこと

実はブラウザソフトって、同一オリジンじゃないと通信を許可しない仕組みになってるのよ

A子

え?
だったら別のサイトの画像を「img」タグで表示したりもできないの?

B美

いいえ
基本的に、禁止されてるのはJavaScriptからのアクセス

例えば、通販サイト(A)にログインした状態で、悪意あるサイト(B)を見たとしましょう
(B)のWebページの中に(JavaScriptによって)(A)の会員情報を表示するURLへのアクセスが記載されてたらどうなる?

C菜

(B)のサイトの運営者(悪意ある人)が、今現在(A)のサイトにログインしている人の会員情報を入手できることになっちゃいますね~(苦笑)

B美

もしも「同一オリジン制限」が無かったら大変なことになるってわけ

仕組みとして素晴らしいのは、デフォルト状態で「異なるオリジンを禁止」していることね
うっかりサーバ設定をミスったりする心配は無いってことよ

A子

なるほどねぇ

ちなみに、異なるオリジンを禁止しているのはサーバなの?
クライアント(ブラウザソフト)なの?

B美

禁止」しているのはブラウザ(クライアント)側よ
そして「許可」する設定を行うのはサーバ側ってわけ

C菜

GoogleMapのWebAPIのように「誰でも自由に使えるようなもの」については、サーバ側で「許可」設定されてるわけですね~?

B美

そういうこと

A子

んで、その設定方法は?

B美

実のところ、なにげに難しいわ

複合的な要因で、CORSポリシーを突破できないことが多々あるの
(OPTIONSが厄介なのよね)

C菜

でも、解決策はあるんですよね~?

B美

もちろん!

cd html/numapp[Enter]
composer require rrd108/cakephp-cors[Enter]
bin/cake plugin load Rrd108/Cors[Enter]

MATE端末」を開いて、上記を打ち込んでね


A子

たったこれだけ?

B美

あと一つ
設定ファイルを書かなきゃいけないわ

「numapp/config」ディレクトリの中に「cors.php」というファイルを作成します

<?php

return [

    'paths' => [
        '/numapp/api/*',
    ],

    'allowedOrigins' => [
        '*'
    ],

    'allowedMethods' => [
        'GET',
        'OPTIONS',
    ],

    'allowedHeaders' => [
        'Content-Type',
    ],

    'exposedHeaders' => [],

    'maxAge' => 0,

    'supportsCredentials' => false,
];

C菜

「paths」の記載は、numappのApiControllerだけが対象ってことでしょうか~?

B美

その通り

管理ページ(numapp/admin)なんかには、アクセスさせたくないからね

A子

allowedOrigins」は「許可されたオリジン」ってことだから、そこには複数のオリジンを(配列要素として)記載するの?

B美

本来はそうなるわね
でもオリジン制限を行わないなら、ワイルドカードである「*」でOK

あと、なにげに重要なのが「allowedMethods」で、必要が無ければ「POST」は省いたほうが良いと思う
でも「OPTIONS」は絶対に必要だから忘れないように!

C菜

「GET」と「POST」は分かりますけど、「OPTIONS」は初めて聞きました~

B美

JavaScriptから異なるオリジンへアクセスする際、いきなりリクエストを行うんじゃなくて、まずCORSを許可しているかどうかを事前に問い合わせることがあるの

それが「OPTIONS」よ

A子

なるほどね

だから「OPTIONS」も許可しておかないとダメなのか

B美

さて、開発環境だけじゃなく、本番環境(VPSサーバ)にも同様の設定を行ったわよ

C菜
冒頭のテストをもう一度行ってみなさい

C菜

うわぁ~
できました~

ばっちり動いてますよ~

A子

これって、「https://friction-river.mydns.jp」というオリジンから、「https://friction-river.jp」という異なるオリジンへアクセスしたってことになるのか…

いよいよWebAPIらしくなってきたね

C菜

ですです~