LaravelのAPI別ドメインからaxiosを使ってアクセス

LaravelでAPIを作っていて、外部のHTMLアプリからAjaxしようとするとクロスドメイン制約にかかって少しはまりました。(POST時に事前にOPTIONSで許可を確認とかCookieを有効にしないとCSRFのセッション切れたりetc.)

結論から

※セキュリティー的には許可の類は制限をするなど要検討。

//サーバー側はMiddlewareでヘッダーを追加
public function handle($request, Closure $next)
{
    $response = $next($request);
    if(APIアクセス判定条件){
        $response->header('Access-Control-Allow-Origin',request()->header('Origin'));
        $response->header('Access-Control-Allow-Credentials', 'true');
        $response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, Authorization, X-CSRF-TOKEN');
        $response->header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    return $response;
}
//POSTなどの前にOPTIONSでリクエストがあるのでRouterに記述追加(許可のヘッダーはMiddlewareで管理なのでこちらは空のレスポンス作るのみ)
Route::options('{all}', function () {
    $response = Response::make('');
    return $response;
});
//クライアント側
axios.defaults.withCredentials = true
axios.defaults.headers.common['Content-Type'] = 'application/json';

if (method === 'get') {
  promise = axios.get(url, { params: params })
} else if (method === 'post') {
  promise = axios.post(url,params,{headers:{'X-CSRF-TOKEN':トークン}});
}

外部ドメインへのAjaxは禁止なのでサーバー側で “Access-Control-Allow-Origin” レスポンスヘッダーを返す。

これはセキュリティー上基本アクセス出来ないのでサーバー側のレスポンスヘッダーに加える必要があります。

$response->header('Access-Control-Allow-Origin',request()->header('Origin'));

クッキーを許可するために ‘Access-Control-Allow-Credentials’ で ’true’を返す。

Cookieを許可するのですが、この値を途中、1(数字)と返してしまいすこしはまった。文字列の’true’でうまくいきました。

$response->header('Access-Control-Allow-Credentials', 'true');

あとはaxios側もCookie送信がOFF ( オプションの withCredentials がfalse)になっているので設定します。

axios.defaults.withCredentials = true

リクエストで許可するヘッダーを ‘Access-Control-Allow-Headers’ で指定

基本的なものと、LaravelのCSRFのチェックに利用する ’X-CSRD-TOKEN’を加えます。

$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, Authorization, X-CSRF-TOKEN');

許可するメソッドを ‘Access-Control-Allow-Methods’ で指定

許可するメソッドを指定します。(APIでGETのみならGETだけなどセキュリティー的云々)

$response->header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');

POSTの前にOPTIONSのリクエストが来る。

最初わからず混乱してたのですが、クロスドメインへPOSTする前にOPTIONSメソッドでpre-flightのリクエストを送信します。

  1. [axios]OPTIONSメソッド送信 →
  2. ←レスポンスを返す。[server]
  3. [axios]ヘッダーを確認(各種設定したOrigin,Header,Methodなどなど)
  4. [axios]各種許可されるならPOST送信