エラー スクリプト
ドメイン ロック、日付ロック、自己防御型の保護といったいくつかの変換は、チェックに応えてコードを実行することができるランタイム チェックです。これらの変換にはすべて任意の構成プロパティ errorScript
があり、このプロパティで、ランタイム チェックがトリガーされたときに実行するスクリプトを提供できます。このセクションでは、保護されるコードにエラー スクリプトを追加する方法を学習します。
構成オプション errorScript
を指定せずに JSDefender を実行する方法
構成プロパティ errorScript
を使用しない場合は、JSDefender により既定の保護が適用されます。
変換 | 既定の保護 |
---|---|
ドメイン ロック | エラーメッセージ ReferenceError: data_value is not defined (ReferenceError: data_value は定義されていません)を発行します。 |
日付ロック | エラーメッセージ ReferenceError: data_value is not defined (ReferenceError: data_value は定義されていません)を発行します。 |
自己防御型の保護 | メッセージ SyntaxError を発行します。 |
SyntaxError
です。コードをランダムに変換すると、その他のエラー メッセージが発行される場合もあります。
JSDefender がエラー スクリプトを使用する方法
保護エンジンは、構成プロパティ errorScript
の文字列値をそのままコードに差し込みます。それでも、保護エンジンは、各エラー スクリプトが JavaScript ブロック ステートメント内で実行されるように管理します。次のエラー処理スニペットがあるとします。
const myMessage = "I got you!";
alert(myMessage);
このスニペットは、次のような記述としてコードに差し込まれ、定数変数 myMessage
には別のスコープが提供されます。
{
const myMessage = "I got you!";
alert(myMessage);
}
エラー スクリプトが差し込まれる場所
エンジンは、ドメイン ロック変換および日付ロック変換のエラー スクリプトを 1 回のみ、JSDefender Runtime という、保護されたコードの適切に防御された部分に差し込みます。複数のファイルを保護している場合、このコードは必ず最初に保護されたファイルに差し込まれます。Runtime にはいくつかの独自の変換(これらは変更、構成できません)が適用されますが、エラー スクリプトにもこれらの変換が適用されます。
これに対し、自己防御型の変換では、保護されたすべての関数にエラー スクリプトが差し込まれます。JSDefender では部分的構成がサポートされているので、保護される複数の関数に異なるエラー スクリプトを割り当てることもできます。このスクリプトには、自己防御型の保護を提供するコードの場合と同様に、いくつかの変換(もう一度言いますが、変更できません)が適用されます。
エラー スクリプトで実行できること
ドメイン ロック保護および日付ロック保護で errorScript
保護オプションを使用すると、以下の操作を行えます。
- いくつかの追加操作を行った後、JSDefender に既定の操作を使用させる。
- いくつかの追加操作を行い、違反が起きていないかのようにコードを実行できるようにする。
自己防御型の保護を使用した場合、追加の操作は実行できますが、JSDefender の既定の操作を回避したり、コードの改ざんが行われなかったかのようにしたりする方法はありません。
JSDefender に既定の操作を適用させる
既定では、JSDefender が既定の操作を実行するのは、エラー ハンドラーが実行された後です。日付ロック変換に次の errorScript
を追加するとします。
const myMessage =
"申し訳ありません。評価期間の有効期限が切れました。" +
"今後、当製品を使用することはできません。";
alert(myMessage);
このコードは、上記のメッセージを表示する警告ダイアログをポップアップ表示し、その後、エラー メッセージ ReferenceError: data_value is not defined
を表示して停止します。
違反がなかったかのように JSDefender を続行させる
コードで return
ステートメントを実行することは、違反を無視するように JSDefender に指示していることになります。そこで、日付ロック変換に次の errorScript
を追加します。
const myMessage = "注意:評価期間の有効期限が切れています。";
alert(myMessage);
return;
このスクリプトでは、上記のメッセージが表示されますが、ユーザーが警告ダイアログを閉じれば、コードは通常どおりに実行されるようになります。
エラー スクリプトの作成
エラー スクリプトを作成する場合、以下の機能を含め、JavaScript のツールセット全体を使用できます。
- 変数、関数、クラスの宣言
- ステートメント
- グローバル関数の呼び出し
- 例外処理(
try..catch..finally
)
ただし、以下の事項に注意する必要があります。
- できれば、コード内で
with
ステートメントやeval
関数を使用しないでください。これらにより、コードが保護の実行後に失敗する可能性があります。 var
宣言は、コードの他の語彙スコープ内の識別子と競合する可能性があるため、慎重に処理してください。- エラー スクリプトのコードにモジュールをインポートしないでください。関数やクラス メソッドを呼び出す必要がある場合は、グローバルな変数またはオブジェクトを介してそれらにアクセスしてください。
async
とawait
を使って非同期コードを使用することもできますが、エラー ハンドラーは同期的に実行されます。
var
宣言の使用
ES 2015 の let
および const
変数のみを使用することをお勧めします。なんらかの理由で var
宣言を使用する必要がある場合に、var
宣言が他の変数名と(偶々)競合する可能性があります。競合した場合は、エラー ハンドラーが失敗します。そのような場合には、即時関数を使用して JavaScript モジュール パターンを使用してください。たとえば、次のスクリプトは使用しないでください。
var myMessage = "I got you!";
alert(myMessage);
代わりに、以下を差し込んでください。
!(function () {
var myMessage = "I got you!";
alert(myMessage);
})();
グローバル関数の呼び出し
JavaScript のグローバル スコープの変数にアクセスできるほか、そこで宣言された関数(JavaScript のグローバル関数を含む)を呼び出すことができます。このため、myDateViolationHandler
というグローバル関数がある場合は、次の errorScript
を適用することができます。
myDateViolationHandler("violated");
myDateViolationHandler
の宣言とその参照の名前変更をエラー ハンドラー スクリプトで管理します。
async
コードの使用
エラー ハンドラーは同期的に実行されます。エラー ハンドラーに async
コードを追加することはできますが、違反があるにもかかわらずアプリケーション コードの実行を許可するのか、それとも停止するのかを決める関数の結果を await
(待機)させることはできません。
次のコードを見てください。
function timeout(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
(async () => {
await timeout(2000);
alert("Invalid date");
return;
})();
一見したところ、このコードには return
があるため、"Invalid date" メッセージが表示された後もアプリケーションの実行を続行できると考えられるかもしれません。しかし、その return は非同期の即時関数から戻るものです。戻るまでに、メッセージが表示されてユーザーに確認されます(2 秒の遅延があることが示されています)。保護エンジンは既定の操作を実行し、ReferenceError
メッセージを表示して停止します。
違反があるにもかかわらずコードの実行を許可するには、次のようにコードに締めくくりの return を追加する必要があります。
function timeout(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
(async () => {
await timeout(2000);
alert("Invalid date");
return;
})();
return; // --- 違反が行われた場合でも続行します
追跡すべきエラー ハンドラー パターン
優れたエラー処理スクリプトを作成するために踏襲すべきシンプルなパターンがあります。その方法をこのセクションで学習できます。
JSDefender は、元のコードの 1 行目よりも前に、ドメインと日付をチェックする保護が実行されるように管理します。このパターンを使用すると、日付違反の結果を格納できます。もちろん、ドメイン違反を管理するのにも類似のパターンを使用することができます。
次のコードをプログラムの先頭に追加します。
let dateViolated;
function signDateViolation() {
dateViolated = true;
}
if (dateViolated) {
// アプリの中止、ユーザーのログアウトなど、
// 日付違反時のロジックをここに追加します
}
// このコードが実行されるのは、制御フローがこのポイントまで到達した場合です
doMyJob();
dateLock
構成に次の errorScript
を追加します。
"dateLock": {
"startDate": "<開始日>",
"endDate": "<終了日>",
"errorScript": "signDateViolation(); return;"
}
エラー ハンドラーは return
ステートメントで終わっているため、日付違反が発生した場合でも、JSDefender はプログラムの流れを続行します。JSDefender は let dateViolated
宣言に到達する前に日付チェック ロジックを実行するので、if
ステートメントが日付条件を評価するまでに dateViolated
変数が正しく設定されることが保証されます。