Dokumentasi
/
Resep
/

Substitusi Template di Sisi Host

Substitusi Template di Sisi Host

Pro
v6.10.0+

Sisipkan nilai hasil render server (misalnya placeholder bergaya template Go `{{ .Field }}`) ke dalam JavaScript hasil obfuskasi VM tanpa merusak alur obfuskasi.

Masalahnya

Backend Anda (Go, Rails, Django, PHP, …) menyajikan berkas JavaScript yang isinya sebagian harus dirender per permintaan: endpoint API, daftar feature flag, blob state awal, ID build, atau nonce. Anda mengobfuskasi JS tersebut dengan vmObfuscation: true, tetapi Anda juga memerlukan template engine untuk mengganti placeholder di keluaran hasil obfuskasi setelah obfuskasi selesai. reservedNames dan reservedStrings menjaga placeholder tetap terlihat di keluaran sehingga dapat diganti. Tanpa keduanya, placeholder string terserap ke dalam bytecode VM dan placeholder pengenal dituliskan di beberapa tempat yang telah ditulis ulang, sehingga template engine tidak menemukan apa pun untuk diganti atau malah merusak keluaran.

Pertimbangkan memuat nilai sebagai data

Jika memungkinkan, hindari mengedit keluaran terlindungi sama sekali: muat konfigurasi runtime sebagai data sebelum bundel terlindungi berjalan. Simpan di skrip terpisah atau ambil dari endpoint yang terautentikasi. Cara ini menjaga keluaran terlindungi tetap utuh, sehingga vmSelfDefending dapat tetap aktif. Data yang dikirim ke peramban bagaimanapun tetap terlihat oleh peramban tersebut.

JavaScript

Gunakan pola di bawah ini ketika nilai-nilai tersebut memang harus disubstitusikan ke dalam berkas hasil obfuskasi.

Catatan tentang contoh Go: contoh-contoh tersebut melakukan penggantian string biasa (strings.ReplaceAll / strings.NewReplacer) pada keluaran hasil obfuskasi dan menangani escaping-nya sendiri, seperti yang ditunjukkan pada setiap pola. Contoh tersebut tidak dijalankan melalui paket html/template Go - paket itu akan menerapkan escaping JavaScript kontekstualnya sendiri di atasnya, sehingga payload mengalami escaping dua kali. Jika Anda memang merender melalui html/template, hilangkan escaping manual dan biarkan engine melakukan escaping sekali saja.

Opsi mana yang harus dipilih?

Nilai server berupa…Gunakan
Nilai JS mentah (array, objek, angka, boolean - nilai JSON apa pun)Pola 1 - reservedNames + placeholder pengenal
String (kasus umum - JSON hasil render, ID build, nonce)Pola 2 - reservedStrings + placeholder template literal
String, ketika kode harus tetap ES5 atau API di sekitarnya membutuhkan literal string bertanda kutipPola 3 - reservedStrings + placeholder string bertanda kutip

Substitusi setelah obfuskasi tidak kompatibel dengan vmSelfDefending: true. Lihat Catatan kompatibilitas di akhir resep ini.

Pola 1 - reservedNames dengan placeholder pengenal

Paling cocok untuk: menyisipkan ekspresi JS mentah (array, objek, angka, …) tanpa perlu memikirkan escaping tanda kutip.

Pilih pengenal khas yang tidak akan pernah bertabrakan dengan kode sungguhan, rujuk secara langsung, dan cantumkan regex yang cocok dengannya di reservedNames. Di bawah obfuskasi VM, pengenal tersebut dialirkan melalui array reserved-expressions dan muncul apa adanya di keluaran, misalnya:

JavaScript

Ganti pengenal dengan ekspresi lengkap hasil serialisasi JSON. Jangan menempelkan nilai di dalam tanda kutip atau backtick: pengenal tersebut tidak berada di dalam literal string, sehingga nilai yang disisipkan diurai oleh engine JS sebagai ekspresi biasa. Gunakan serializer tepercaya, lakukan escaping pada < ketika skrip disematkan dalam HTML, dan uji nilai yang berisi tanda kutip, backslash, baris baru, backtick, dan ${...}.

JavaScript

Pola 2 - reservedStrings dengan placeholder template literal

Paling cocok untuk: template engine bergaya Go / Jinja yang mewajibkan delimiter seperti {{ .Field }}, yang kebetulan merupakan teks JS yang valid bila dibungkus backtick.

Placeholder berada di dalam template literal dengan satu quasi dan tanpa interpolasi. Di bawah obfuskasi VM, ini dialirkan melalui array reserved-expressions, sehingga bentuk backtick mentahnya tetap terjaga di keluaran.

Sumber

JavaScript

Opsi obfuscator

UI

Untuk mencadangkan placeholder {{.Config.FeatureFlags}} dari sumber di atas, tambahkan regex ini ke field Reserved Strings dengan backslash tunggal. UI menyimpan nilai apa adanya, jadi tidak seperti di kode JS, backslash tidak digandakan:

Teks

Field Reserved Strings di UI obfuscator dengan regex yang dimasukkan menggunakan backslash tunggal

API

JavaScript

Setelah obfuskasi

JavaScript

Placeholder dipertahankan byte demi byte, termasuk backtick yang mengapitnya.

Substitusi di sisi host

Ganti {{.Config.FeatureFlags}} dengan string JSON yang sudah diberi escaping untuk template literal. Backtick tidak memerlukan escaping " di dalamnya, tetapi backslash, backtick, atau ${ di dalam payload tetap akan mengubah atau mengakhiri literal, jadi lakukan escaping pada ketiganya:

Kode

Saat runtime: JSON.parse(`{"newCheckout":true,"darkMode":false}`) - berfungsi.

Mengapa template literal lebih disukai daripada tanda kutip tunggal/ganda untuk nilai string? Backtick tidak memerlukan escaping " di dalam payload JSON. Ini penting karena sebagian besar nilai hasil render server adalah JSON, dan JSON penuh dengan tanda kutip ganda. Dengan placeholder bertanda kutip ganda, Anda harus melakukan escaping pada setiap " di dalamnya (lihat Pola 3); dengan backtick, payload hanya perlu escaping pada backslash, backtick, dan ${ yang jarang muncul.

Pola 3 - reservedStrings dengan placeholder string bertanda kutip

Paling cocok untuk: kode sumber yang harus tetap ES5 (tanpa template literal), atau kasus ketika API di sekitarnya mengharapkan literal string biasa.

Placeholder berupa literal string bertanda kutip tunggal atau ganda. Di bawah obfuskasi VM, ini dialirkan melalui array reserved-strings, yang dikeluarkan sebagai array JS hasil serialisasi JSON.stringify - selalu bertanda kutip ganda, apa pun gaya tanda kutip pada masukan.

Sumber

JavaScript

Opsi obfuscator

UI

Untuk mencadangkan placeholder {{.Page.Tags}} dari sumber di atas, tambahkan regex ini ke field Reserved Strings dengan backslash tunggal. UI menyimpan nilai apa adanya, jadi tidak seperti di kode JS, backslash tidak digandakan:

Teks

Field Reserved Strings di UI obfuscator dengan regex yang dimasukkan menggunakan backslash tunggal

API

JavaScript

Setelah obfuskasi

JavaScript

Substitusi di sisi host

Karena placeholder berada di dalam string JS bertanda kutip ganda, payload JSON yang disisipkan harus diberi escaping pada backslash dan karakter " di dalamnya:

Kode

Keluaran yang dihasilkan:

JavaScript

Saat runtime: JSON.parse("[\"news\",\"tech\",\"release\"]") → ["news","tech","release"].

Jika Anda lupa melakukan escaping, peramban akan melihat tanda kutip yang tidak seimbang dan melempar SyntaxError. Pola 2 menghindari tanda kutip ganda sepenuhnya dengan menggunakan backtick.

Beberapa placeholder dalam satu program

Ketiga pola dapat dipadukan. Satu regex reservedStrings dengan alternasi dapat mencocokkan setiap bentuk placeholder yang dikeluarkan template engine Anda - di sini, gaya {{ .Field }} maupun %{ .Field }:

JavaScript

Anda dapat mencampur placeholder pengenal (untuk nilai JS mentah) dan placeholder string (untuk JSON hasil render) dalam sumber yang sama; pilih per placeholder berdasarkan apa yang benar-benar akan disisipkan oleh server.

Catatan kompatibilitas

vmSelfDefending merusak substitusi setelah obfuskasi

VM Self Defending mendeteksi setiap perubahan pada keluaran hasil obfuskasi setelah build, termasuk substitusi template yang sah, dan kode terlindungi kemudian menolak berjalan.

Jika Anda mengandalkan substitusi template di sisi host, setel vmSelfDefending: false. Biarkan selfDefending juga nonaktif: opsi ini tidak berpengaruh di bawah obfuskasi VM, dan tanpa VM opsi ini juga melarang perubahan apa pun pada keluaran.

Tips placeholder

  • Jangan memakai ulang placeholder untuk pengenal dan string sekaligus. Nama tercadang seperti __TOKEN__ dan string tercadang yang cocok dengan __TOKEN__ menggambarkan dua jalur kode yang berbeda (array reserved-expressions vs. array reserved-strings). Gunakan bentuk teks yang berbeda untuk masing-masing, misalnya konvensi UPPER_SNAKE untuk placeholder pengenal dan bentuk yang dibungkus delimiter ({{ ... }}, %{...}, <<<...>>>) untuk placeholder string. Dengan begitu, bug pada satu regex tidak dapat diam-diam mencocokkan yang lain.
  • Regex reservedStrings dijalankan terhadap nilai string mentah. Regex dicocokkan dengan nilai runtime string, bukan teks sumbernya. \{\{[^}]+\}\} mencocokkan string yang mengandung {{.something}} (atau bentuk {{...}} lainnya). Jika placeholder Anda mungkin dibungkus konten tambahan ("prefix-{{.Field}}-suffix"), regex tetap cocok tetapi seluruh string dipertahankan, jadi rencanakan substitusi Anda dengan memperhitungkannya.
  • Berfungsi dengan template engine apa pun. Meskipun contohnya menggunakan sintaks Go, tidak ada bagian integrasi javascript-obfuscator yang khusus untuk Go. Apa pun yang dapat melakukan penggantian tingkat string pada keluaran obfuscator akan berfungsi: Rails ERB, Django, short tag PHP, sed dalam pipeline CI, dan sebagainya. Pilih delimiter yang secara alami dikeluarkan oleh engine Anda dan tidak bertabrakan dengan sintaks JS sungguhan.