LoginSignup
8
6

More than 5 years have passed since last update.

【Lumen】Lumen製APIに対してクロスドメインアクセスを行う(CORS)

Last updated at Posted at 2018-04-06

異なるドメインからアクセスしようとするとエラーが返される

異なるドメインでアクセスしようとすると以下のようなエラーが出るのは周知のことかと思います。(クロスドメイン制約)

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://★★★★★★★★★★' is therefore not allowed access.

クロスドメインアクセスを行う場合はCORS(Cross-Origin Resource Sharing)の仕組みを使用する必要がある

LumenでCORSを使用する

以下のファイルを\app\Http\Middlewareに作成する。

CorsMiddleware.php
<?php

namespace App\Http\Middleware;
use Closure;

class CorsMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // TODO:Access-Control-Allow-Originを適切に指定する必要がある
        $headers = [
            'Access-Control-Allow-Origin'      => '*',
            'Access-Control-Allow-Methods'     => 'POST, GET, OPTIONS', // TODO:この部分も適切に設定する必要がある
            'Access-Control-Allow-Credentials' => 'true',
            'Access-Control-Max-Age'           => '86400',
            'Access-Control-Allow-Headers'     => 'Content-Type, Authorization, X-Requested-With'
        ];

        // preflightリクエスト用
        if ($request->isMethod('OPTIONS'))
        {
            return response()->json('{"method":"OPTIONS"}', 200, $headers);
        }

        $response = $next($request);
        foreach($headers as $key => $value)
        {
            $response->header($key, $value);
        }

        return $response;
    }
}

そして、\bootstrap\app.phpに以下を追加する。

app.php
$app->middleware([
    App\Http\Middleware\CorsMiddleware::class
 ]);

これで、ヘッダーにAccess-Control-Allow-Originが追加されてクロスドメイン間でもアクセスを行うことができる。

もし本番と開発環境で切り分ける必要があるなら.envファイルに書いて読み込むようにしておけばいいんじゃないですかね。

.env.example
ACCESS_CONTROL_ALLOW_ORIGIN=*

ちなみにpreflightリクエストとは目的の通信をする前に事前に安全かどうかを確かめるリクエストのことをさします。

「プリフライト」リクエストは始めに OPTIONS メソッドによるリクエストを他のドメインにあるリソースに向けて送り、実際のリクエストを送信しても安全かどうかを確かめます。サイト間リクエストはユーザーデータに影響を与える可能性があるため、このようにプリフライトを行います。

引用:オリジン間リソース共有 (CORS) - HTTP | MDN

Basic認証をかけているサーバーにあるAPIに対してアクセスをする場合

Access-Control-Allow-Originにワイルドカード*を指定してると以下のようなエラーが出る。

The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
Origin 'http://★★★★★★★★★★' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

ようはちゃんと指定して書けといわれてるのでAccess-Control-Allow-Originにちゃんとアクセス先を記述する必要がある。

CorsMiddleware.php
'Access-Control-Allow-Origin'      => 'http://★★★★★★★★★★',

あとクレデンシャルが必要な場合はAccess-Control-Allow-Credentialstrueにしておくこと。

クレデンシャル・・・ユーザーの認証に用いられる情報の総称。ここではCookieやベーシック認証のID、パスをさす。

CorsMiddleware.php
'Access-Control-Allow-Credentials' => 'true',

また、JavaScriptからAjaxで通信する際にクレデンシャルが必要な場合はJavaScript側でオプション設定する必要があります。
JavaScript(ここではjQuery)側のオプション設定を載せておきます。

post.js
        function sendPostToApiByAjax()
        {
            $.ajax({
                type:     "POST",
                url:      "http://★★★★★★★★★★",
                // username: "*****", // Basic認証用ユーザー名
                // password: "*****", // Basic認証用パスワード
                data: {
                    name : 'ajaxAPI' // リクエストパラメータ
                },
                xhrFields: {
                    withCredentials: true // クレデンシャル送るよオプション
                },
            }).done(function(data) {

                console.log('Successful communication with API!');

            }).fail(function(data) {
                console.log('Ajax fail (communication error)');
            });
        }

おわり

  • CORSむずかしい
  • Laravelはbarryvdh/laravel-corsを入れたらよさげ(Lumenも対応してるみたいですがうまくいかなかった・・・)

参考

以下CORSに関して参考させていただいたサイト

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6