B3S
menu close

雑記

JavaScriptでCORBのエラーに出会いました


edy

公開日:2021/10/26


JavaScriptでCORBのエラーに出会いました

この記事では、次の事を記載しています。

目次

  • 1. きっかけ
  • 2. CORBとは
  • 3. CORB対応策
  • 4. まとめ

1.きっかけ

社内システムに、住所入力補助機能をつけたいと思い、
郵便番号検索のAPIを利用しました。
APIを実行するためにアプリケーションIDなるものが必要なため、新たに作成して、サンプルコード通りに実装しました。
APIを実行すると、何やらエラーが。
ChromeブラウザのDevToolでエラーを確認すると「from origin ‘http://xxx.xxx.xxx.xxx’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present」と出てます。
そもそもこのエラーは何?どうやって回避するの?を記載しました。

2.CORBとは

エラーの内容は何か。
Qiitaの記事
Googleのドキュメント。。 長い

セキュリティを確保するためのWebブラウザの仕組みで、
ブラウザから別オリジン(ドメイン + ポート)へのアクセスを制限するというものです。

引用元「Qiita記事

今回の例でいうと、
http://xxx.xxx.xxx.xxxから、外部のサービスのAPIを呼び出したためです。
さてどうしましょう。

3.CORB対応策

対策として3つ検討しました。

  1. サーバーにレスポンスヘッダーを追加する
  2. クライアント側でAPI呼び出し時に、オプションを指定
    fetch('https://外部API', {
    mode: 'cors'
    });

    サーバーサイドで、レスポンスヘッダーに以下を追加

    Access-Control-Allow-Origin: https://外部API // 特定のサイトを許可する
    Access-Control-Allow-Headers "X-Requested-With, Origin, X-Csrftoken, Content-Type, Accept"


    しかし、この方法は、サーバーに設定追加しなければならず、手間がかかります。
    サーバーを変更するなどの実行環境が変われば再度、設定する必要があるため、運用負荷が高いです。

  3. JSONPを使う
  4. scriptタグのsrc属性に外部APIを指定する方法です。
    ヤフーのJSONP実装サンプルのページがあります。

    //JSONPを実行する関数
    //scriptタグを生成してsrc属性に追加
    function callJSONP(url) {
    var target = document.createElement('script');
    target.charset = 'utf-8';
    target.src = url;
    document.body.appendChild(target);
    }

    つまり、こんなソースになる

    詳しくはZennのこの記事

    しかし、この方法は依然セキュリティ上のリスクがあります。
    https://ja.wikipedia.org/wiki/JSONP
    「悪意のあるサイトがJSONデータを取得するといったことが可能である。」

  5. クライアントからの呼び出しをやめる
  6. サーバー側で外部APIを呼び出し、結果をjsonにしてクライアント側に返却します。

    $url = "https://外部API/";

    // cURLセッションを初期化
    $ch = curl_init();

    // オプションを設定
    curl_setopt($ch, CURLOPT_URL, $url); // 取得するURLを指定
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 実行結果を文字列で返す
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // サーバー証明書の検証を行わない

    // URLの情報を取得
    $response = curl_exec($ch);

    // 取得結果を表示
    echo $response;

    // セッションを終了
    curl_close($conn);


    若干面倒ですが、この方法がセキュリティを担保しつつ、Javascript

4.まとめ

クライアントからの呼び出しをやめて、サーバー側で外部APIにアクセスするようにしました。3 – 3を採用。