複数ファイルの保護
JSDefender は、アプリケーションで複数の JavaScript ファイルを使用する場合のシナリオを管理しています。
複数のファイルを使用する場合、ファイル間に相互関係があることがあるため、ファイルを別々に保護することは通常できません。複数ファイルの読み込み順を適切に指定しておけば、JSDefender により、各ファイルに保護が正しく適用されます。
複数ファイルの指定
複数のファイルを保護するには、構成ファイルの inputs
セクションにそれらのファイルを指定し、Web ページに読み込まれる最初のファイルを示す必要があります。そこで、直前の例で使用した 2 つのファイルを保護するとしましょう。
file1.js
:
function getGreeting() {
var name = getName();
return "Hello, " + name + ", from multifile demo!";
}
file2.js
:
function getName() {
return "Developer";
}
var element = document.getElementById("msg");
element.textContent = getGreeting();
次に、以下の構成ファイルを使用します(file1.js
と file2.js
は、jsdefender.config.json
と同様に現在の作業フォルダーにあるとします)。
jsdefender.config.json
:
{
"inputs": ["file1.js", "file2.js"],
"settings": {
"localDeclarations": {
"nameMangling": "sequential"
},
"stringLiterals": false
}
}
jsdefender
コマンド ラインを実行した後、保護された出力ファイルは次のとおりです。
file1.js
:
function _0x000000() {
var _0x000001 = _0x000002(); // file2.js で宣言された ID
return "Hello, " + _0x000001 + ", from multifile demo!";
}
file2.js
:
function _0x000002() {
// file1.js にはこの ID への参照があります
return "Developer";
}
var _0x000003 = document.getElementById("msg");
_0x000003.textContent = _0x000000();
識別子 _0x000002
を見てください。これは、元のコードにある getName
を名前変更したバージョンです。保護されたファイルのどちらでも正しく置き換えられています。
ファイルの順序が重要な理由
このドキュメントの冒頭で学習したことをさらに詳しく説明すると、JSDefender Runtime を単一ファイルにのみ差し込む場合は、入力一覧で、Web ページに読み込まれる最初のファイルを JSDefender に提供していることを確認する必要があります。後続の入力の順序はその後問題になりません。
runtimeInjection
モードが既定値(firstNonModule
)になっている場合は、JSDefender は isModule
フラグが付けられていない最初の入力ファイルに差し込まれます。
runtimeInjection
モードが separateSource
に設定されている場合は、JSDefender Runtime は別のソース ファイルに差し込まれるため、そのファイルが Web ページに最初に読み込まれる必要があります。
しかし、runtimeInjection
モードが all
に設定されている場合、JSDefender Runtime はすべての入力に差し込まれます。つまり、すべてのファイルが独自のランタイムを使用するため、この場合には、入力の順序はまったく重要でないということです。
複数のファイルが単一のページに読み込まれる場合の問題
同一の Web ページに読み込まれる 2 つのファイルを別々に保護した場合に、実行中のコードが失敗する可能性がある短い例を見てみましょう。
ローカル宣言の名前変更(名前の改変)は、意味のある識別子を意味のない英数字列に変更するので、優れた保護オプションです。ただし、複数のファイルがある場合に、それらのファイルに対して別々に JSDefender を使用すると、コードが失敗する可能性があります。その実例を次に示します。
file1.js
と file2.js
の 2 つのファイルがあるとします。これらのファイルはブラウザーにより次の順序で HTML ページに読み込まれます。
...
<script src="file1.js"></script>
<script src="file2.js"></script>
...
file1.js
:
function getGreeting() {
return "Hello from multifile demo!";
}
file2.js
:
var element = document.getElementById("msg");
element.textContent = getGreeting();
これら 2 つのファイルは、JSDefender CLI を 2 回(ファイルごとに 1 回)実行することで保護できます。これにより、次のファイルがローカル宣言の名前変更後に得られます。
file1.js
(保護済み):
function _0x000000() {
return "Hello from multifile demo!";
}
file2.js
(保護済み):
var _0x000000 = document.getElementById("msg");
_0x000000.textContent = getGreeting();
次の 2 つの問題があります。
- どちらのモジュールにも
_0x000000
という宣言が含まれています。JavaScript の宣言ホイスティング(巻き上げ)メカニズムにより、1 番目の_0x000000
宣言が 2 番目の同じ宣言(file2.js
内)で上書きされます。 file2.js
のgetGreeting
は、ローカル宣言ではなく単なる識別子の参照であるため、名前変更されません。
このコードは、ページがブラウザーで読み込まれると、失敗します。
2 つの JavaScript ファイルを同様に使用する次のシナリオをご覧ください。
file1.js
:
function getGreeting() {
var name = getName();
return "Hello, " + name + ", from multifile demo!";
}
file2.js
:
function getName() {
return "Developer";
}
var element = document.getElementById("msg");
element.textContent = getGreeting();
各ファイルに対して JDSefender を別々に呼び出すと、以下が得られます。
file1.js
(保護済み):
function _0x000000() {
var _0x000001 = getName();
return "Hello, " + _0x000001 + ", from multifile demo!";
}
file2.js
(保護済み):
function _0x000000_() {
return "Developer";
}
var _0x000001 = document.getElementById("msg");
_0x000001.textContent = getGreeting();
このコードも失敗することがすぐにわかります。
- どちらのファイルにも
_0x000000
という宣言が含まれています。JavaScript の宣言ホイスティングにより、1 番目の宣言がfile2.js
内の宣言で上書きされます。 file1.js
のgetName
は、ローカル宣言ではなく単なる識別子の参照であるため、名前変更されません。file2.js
のgetGreeting
は、ローカル宣言ではなく単なる識別子の参照であるため、名前変更されません。
このため、JSDefender を複数のファイルと共に使用する場合は、ファイルの順序に注意してください。