PHPでもjavascriptでもeval関数を使うことはセキュリティ上よろしくないという事が色々なサイトに書かれていますが、使わなくてはいけない場合が度々あります。
もちろん、セキュリティ対応は確実にやることが前提で使うのですが、この際に強制的にプログラム実行をするeval関数で、任意のコードを実行させる時に、ユーザーがコードを作り出せるような仕組みの場合、エラーを出してしまって画面が真っ白になってしまう(またはエラーコードが表示される)という事は容易に想像できる。
これを回避するには、try~catchを使えば良いのだけれど、今回は、リファレンスサイトに書いてある通りにtry~catchを書いた時に想定通りの動作がしなかったという事を書いておきます。
evalを使うレアケース
そもそもevalを使わなければいけないシチュエーションとはどういう場合かと言うと、計算式を任意で設ける仕様などです。
B2Bシステムで、ユーザーが任意の計算式を設置しなければならないような仕様ですね。
例えば経営指標を表示する場合に、企業や部門、担当者によって表示したい数値は違います。
経営者であれば、全体の売上から経費を覗いた利益を知りたいと思うし、部門であれば、部門単体の経費、利益、構成比などを表示したいはずです。
こうした場合に、設定項目として、値の元データを登録して、それらを自由に四則演算させるにはeval関数を使うのが最も効率的です。
置き換え文字などで数字に変換してあげればいいだけなんですが、プログラムリテラシの無いユーザーなどの場合に、四則演算の後ろに数値を入れないとエラーになるという事などお構いなしです。
そうした場合の対応としてeval関数のエラーを判定しなければなりません。
try~catchの書き方とその概要
まずは基本のおさらいをしておきたい。
色々なリファレンスサイトを見ると以下のように書くことを記しています。
try {
eval('$content = (100 - );');
} catch (Throwable $t) {
$content = null;
}
http://php.net/manual/ja/function.eval.php
こちらのマニュアルサイトに記述されているとおりに、コピペしてみたところ、何故か私の環境では、catchがうまく動作しませんでした。
なぜだかわからず他のサイトをググりまくってみたが、同じ状態でした・・・
namespaceに気をつけろ
解凍は意外とシンプルなもので、上記の"Throwable"は、PHPのグローバル関数のようで、これを呼び出しているという事だったので、僕の使っている環境は、特殊なフレームワークで、全ての関数にはclass有り無しに関わらず"namespace"を付与しなければならないことを思い出し、
以下のようにすることで解決しました。
try {
eval('$content = (100 - );');
} catch (\Throwable $t) {
$content = null;
}
間違い探しのようになっていますが、Throwable関数を、root-namespaceから呼び出せるようにバックスラッシュを付けることで、今現在のnamespaceに縛られること無く関数実行ができるようになったようです。
こんなシンプルな対応ですが、使い慣れていないと、こういう出来事に小一時間とられてしまうという自分への戒めの為にブログにかおておきました。
この記事が、どなたかの参考になることを祈ります・・・
0 件のコメント:
コメントを投稿