Asial Blog

Recruit! Asialで一緒に働きませんか?

symfony + PHPスクリプト暗号化(ionCube)

カテゴリ :
バックエンド(プログラミング)
タグ :
Tech
PHP
暗号化
symfony
こんにちは井川です。今回は、symfonyに組み込んだPHPスクリプトを暗号化した際に。アプリケーションを正常に動作させる簡単な方法をご紹介します。この方法を使うことで、実際にionCubeでPHPスクリプトを暗号化しても正常に動作します(その他のエンコーダでも同様だと思います)。

symfonyは、libディレクトリ、apps/アプリ/libディレクトリ、apps/アプリ/module/*/lib以下のPHPファイルとクラスの対応関係を自動的に生成し、cacheディレクトリ以下にキャッシュファイルとして保存します(cache/アプリ/環境/config_autoload.yml.php)。そして次回からは、そのキャッシュファイルを用いてautoloadを実行します。このキャッシュファイル生成方法はいたって簡単です。上記libディレクトリ内の全PHPスクリプト(lib/vendor/symfonyなどは除く)を文字列として読み込み、その文字列からクラス名を抽出します。デフォルトでは、sfAutoloadConfigHandlerクラスがこの役割を担っており、parse()メソッド内部で上記の処理を行います。

PHPスクリプトの暗号化を使うと、キャッシュファイル生成時に各PHPファイルを文字列として読み込んでも、クラス名を抽出できません。このため、symfony実行時にエラーが発生します。

そこで今回はアプリケーションが正常に動作するように、上記キャッシュファイルを生成するクラスを新たに作ります。そして、symfonyで使われるように設定します。方法はとても簡単です。

まず、PHPファイルへのクラス定義時に以下の2つの制約を設けます。

①1ファイルに1クラス
② PHPファイル名は「クラス名.class.php」

そして、新しいクラスでは、ファイル名からそのファイル内に記述されているクラス名を取得し、クラス名とPHPファイルの絶対パスの関係を取り出します(config_autoload.yml.phpに記述)。

実際に、デフォルトでクラス名とファイルパスの関係を抽出しているのは、sfAutoloadConfigHandlerクラスの113~115行目です。

  1. <?php
  2.   ...
  3.   foreach ($finder->in($matches) as $file)
  4.   {
  5.     $mapping = array_merge($mapping, $this->parseFile($path, $file, isset($entry['prefix']) ? $entry['prefix'] : ''));
  6.   }
  7.   ...

そこで、sfAutoloadConfigHandlerクラスを継承したTestAutoloadConfigHandlerクラスを次のように実装します。

  1. <?php
  2. class TestAutoloadConfigHandler extends  sfAutoloadConfigHandler
  3. {
  4.   protected function parse(array $configFiles)
  5.   {
  6.     ...
  7.       foreach ($finder->in($matches) as $file)
  8.       {
  9.         $file_name = basename($file);
  10.         
  11.         if (preg_match('/^(.+)\.class\.php$/i', $file_name, $m))
  12.         {
  13.           $mapping[strtolower($m[1])] = $file;
  14.         }
  15.       }
  16.     ...
  17.   }
  18. }

このクラスを使用するために、configディレクトリにconfig_handlers.ymlを設置します。内容は以下の通りです。

  1. config/autoload.yml:
  2.   class:    TestAutoloadConfigHandler

さらに、config/ProjectConfiguration.class.phpの先頭部分で、先のハンドラクラスを読み込みます。

  1. <?php
  2. require_once dirname(__FILE__).'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';
  3. sfCoreAutoload::register();
  4. require_once dirname(__FILE__) . '/../lib/config/TestAutoloadConfigHandler.class.php';
  5.  
  6. ....

後は、暗号化を行い、暗号化スクリプトを使用する環境でsymfony ccを実行します。これで暗号化スクリプト+symfonyを使用できます。

ここでご紹介した方法は簡易的なものです。他のライブラリで、1つのファイルに複数のクラスを記述しているものや、ファイル名とクラス名が一致しないものを使う場合には、TestAutoloadConfigHandlerクラスを適切に書き直さなければなりません。必要に応じて試してみて下さい。