LaravelでCORS設定のベストな方法は何か
これには2種類の方法があると考えてます。
- ライブラリを使って設定
- header関数を使って設定
個人的にはライブラリで楽したいと思ったんですが、なぜか上手くいかなくて困りました。そんな時は2つめのheader関数で自力で設定する必要もありますね。
CORS設定のポイント・具体的方法を解説します!
このページの目次
CORS設定してないとAjax通信でエラーが出る
そもそもCORSとは何なのか
その説明はMDNでは次のように説明されてます。
オリジン間リソース共有(CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。ウェブアプリケーションは、自分とは異なるオリジン (ドメイン、プロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。
ちょっと具体的なイメージが湧きにくいかも
例えば通信先が hogehoge.com だとしましょう。それに fugafuga.com からRest APIを叩きたいとかの場合、CORS設定してないとアクセス拒否されます。
ググると小難しい専門用語連発の記事がたくさんヒットしますが、つまりは「他ドメイン(異なるオリジン)からサービス提供元のドメインへのアクセスを許可する設定」をできるのがCORSってことです。
具体例 : ”No 'Access-Control-Allow-Origin' header”エラーが出る
具体的にAjaxで説明してみます。
例えばこういう状況を考えてみてください。
- hoge.com : サービス提供元
- fuga.com : APIとかを呼び出したい側
具体的にfuga.comからAjax通信してみます。
▼ hoge.comで提供されてるRestAPIにアクセス
1 2 3 4 5 6 7 8 9 10 |
/// fuga.com から呼び出されたコード jQuery.ajax({ 'url': 'https://hoge.com/api/posts', 'type': 'GET', 'dataType': 'json', }).then( function(data){ console.log(data) } ); |
このケースでは https://hoge.com/api/post みたいなRest APIが提供されており、それを外部ドメイン(fuga.com)から利用したいという場合です。
CORS設定してないと、こんなエラーが出ちゃいます。
1 |
Access to XMLHttpRequest at 'https://hoge.com/api/posts/' from origin 'https://fuga.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. |
「No 'Access-Control-Allow-Origin' header is present」
jQuery+Ajaxでコードを書いてると、割と遭遇することが多いエラーだと思います。これは自分の書いたコードに問題があるわけではなく、通信先が接続元ドメインを許可していないから起きることです。
長くなったけど、これがCORS設定してない問題点
解決策1.ライブラリを使ってCORS設定する
ここからはlarabelでのCORS設定の具体策について
1つめは laravel-cors というライブラリを使う方法
▼ GitHub公開されてるライブラリ
これを使うと簡単にCORS設定できるらしいです。
その設定手順を簡単に書くならこうなります。
▼ まずcomposerからライブラリインストール
1 |
composer require fruitcake/laravel-cors |
▼ app/Http/Kernel.phpにミドルウェア追加
1 2 3 4 5 |
protected $middleware = [ // ... \Fruitcake\Cors\HandleCors::class, // ... ]; |
▼ artisanから設定ファイルを生成
1 |
php artisan vendor:publish --tag="cors" |
設定ファイルは config/cors.php として生成されるので、そこに許可したいHTTPメソッド・許可したいドメイン(オリジン)を色々設定できるみたいです。
詳しくは次記事なんかも参考になるかも
なぜか fruitcake/laravel-cors が機能しなかった...
僕の場合、なぜかこのライブラリが使えなかったです。
▼ 原因として考えられること
- レスポンス時に echo(), dd() で出力してる
- レスポンス時にdie(), exit() で終了している
- ヘッダー出力が何かしら重複している
このライブラリでは echo() , dd() , die() , exit(), dump() を呼び出すとミドルウェアの処理が阻害されるらしいです。ヘッダー出力前にそういった関数を使ってたのかもしれません。
だからライブラリ以外の方法を探すことにしました。
※ 使えるならライブラリを使う方が楽だし確実
解決策2.header関数から Access-Control-Allow-Origin などを設定
2つめは原始的にheader関数を使ってみる方法
追加場所は bootstrap/app.php などでOKです。
具体的なコード例を出すならこういう感じです。
▼ bootstrap/app.php に追加したコード
1 2 3 4 5 6 7 8 9 10 |
$allowed_origins = [ 'https://fuga.com', 'https://piyo.com' ]; $origin = @$_SERVER['HTTP_ORIGIN']; if(in_array($origin, $allowed_origins)){ header('Access-Control-Allow-Origin: '.$origin); header('Access-Control-Allow-Methods: *'); header('Access-Control-Allow-Headers: *'); } |
このようにアクセス許可するドメイン一覧を $allowed_origins と指定定義し、 $_SERVER['HTTP_ORIGIN'] がそれに当てはまるなら header('Access-Control-Allow-Origin: '.$origin); などでアクセス許可してるだけです。
この方法の欠点は次のようなこと
- 全てのパスで同じCORS設定になる
- 特定URLだけのCORS設定が難しい
例えば https://hoge.com/api/* だけCORS設定したいとしたら、リクエストURLから判断するとか少し工夫が必要になりますね(面倒だけど不可能ではない)
CORS設定は面倒でも必ずしておいた方がいい
この2つの方法のどちらかで設定可能です。
- ライブラリを使ってCORS設定する
たとえば fruitcake/laravel-cors のようなライブラリを導入する。設定も楽だが、レスポンス時に echo(), dd(), die(), exit() で出力・終了してると正常に動かないようなので注意
- Access-Control-Allow-Origin などを設定
たとえば bootstrap/app.php などでheader関数を使ってアクセス許可するドメインだけ Access-Control-Allow-Origin を付与するような方式。もしライブラリが使えないなら試す価値あり
僕の場合、運悪くライブラリが動かず原因特定もできませんでした。だから2番目の方法を使ったのですが、当然ながらライブラリを使う方が確実です。
以上、LaravelでのCORS設定についてでした。
間違い・ご指摘はコメント欄からどうぞ、ではまた