Host-side Template Substitution
Sunucu tarafından oluşturulan değerleri (örneğin Go html/template `{{ .Field }}` ifadeleri) obfuscation işlem hattını bozmadan VM ile obfuscate edilmiş JavaScript'e enjekte edin.
Sorun
Backend'iniz (Go, Rails, Django, PHP, …), içeriği istek başına kısmen oluşturulması gereken bir JavaScript dosyası sunar
- bir API uç noktası, bir özellik bayrakları listesi, bir başlangıç durumu blob'u, bir derleme kimliği, bir nonce. JS'i
vmObfuscation: trueile obfuscate edersiniz, ancak aynı zamanda şablon motorunun, obfuscation bittikten sonra obfuscate edilmiş çıktıdaki yer tutucuları değiştirmesi gerekir. Yer tutucular VM bayt koduna (dizeler ve tanımlayıcılar için varsayılan) dahil edilirse, şablon motorunun değiştirecek bir şeyi kalmaz.
Hangi seçeneği seçmeliyim?
| Sunucu değeri… | Kullanın |
|---|---|
| Bir ham JS ifadesi (dizi değişmezi, nesne, sayı, boolean, fonksiyon çağrısı) | reservedNames + tanımlayıcı yer tutucu |
| Bir string ve şablon sınırlayıcılarını siz kontrol ediyorsunuz | reservedStrings + şablon değişmezi yer tutucu |
Bir string ve şablon motoru belirli sınırlayıcıları zorunlu kılıyor (örneğin Go {{ .Field }}) | reservedStrings + string veya şablon değişmezi yer tutucu |
Kalıp 1 - tanımlayıcı yer tutucu ile reservedNames
En uygun: sıfır tırnak kaçışı endişesiyle ham JS ifadeleri (diziler, nesneler, sayılar, …) enjekte etmek.
Gerçek kodla asla çakışmayacak ayırt edici bir tanımlayıcı seçin, ona doğrudan başvurun ve reservedNames içinde onunla
eşleşen bir regex listeleyin. VM obfuscation altında, tanımlayıcı ayrılmış-ifadeler dizisi üzerinden yönlendirilir ve
çıktıda birebir görünür.
Kaynak
(function () {
var initialState = __INITIAL_STATE__;
bootstrap(initialState);
})();
Obfuscator seçenekleri
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
reservedNames: ['^__INITIAL_STATE__$']
});
Obfuscation'dan sonra
Çıktının bir yerinde şuna benzer bir ayrılmış-ifadeler dizisi bulacaksınız:
let _r = [__INITIAL_STATE__, /* …other entries… */];
__INITIAL_STATE__ belirteci, tanımlayıcı yeniden adlandırmadan kurtulur ve VM bayt koduna dahil edilmez.
Sunucu tarafı değiştirme (Go örneği)
tpl := template.Must(template.New("obf.js").Parse(obfuscated))
tpl.Execute(w, map[string]any{
"InitialState": map[string]any{"user": "alice", "theme": "dark"},
})
…burada Go şablonunuz belirteci ham bir JS ifadesiyle değiştirir:
{{ `__INITIAL_STATE__` }} → {{ .InitialState | toJSON }}
Sonuç:
let _r = [{"user":"alice","theme":"dark"}, /* … */];
Tırnak yok, kaçış yok - enjekte edilen değer, JS motoru tarafından sıradan bir ifade olarak ayrıştırılır.
Kalıp 2 - şablon değişmezi yer tutucu ile reservedStrings
En uygun: ters tırnak içine alındığında geçerli JS metni olan {{ .Field }} gibi sınırlayıcılar gerektiren Go /
Jinja tarzı şablon motorları.
Yer tutucu, tek-parçalı, değer yerleştirmesi olmayan bir şablon değişmezi içinde yaşar. VM obfuscation altında bu, ayrılmış-ifadeler dizisi üzerinden yönlendirilir ve çıktıda ham ters tırnak biçimini korur.
Kaynak
(function () {
var featureFlags = JSON.parse(`{{.Config.FeatureFlags}}`);
applyFlags(featureFlags);
})();
Obfuscator seçenekleri
Arayüz
Yukarıdaki kaynaktan {{.Config.FeatureFlags}} yer tutucusunu ayırmak için, bu regex'i Reserved Strings alanına tek
ters eğik çizgilerle ekleyin. Arayüz değeri birebir saklar, bu nedenle JS kodundakinin aksine ters eğik çizgiler ikiye
katlanmaz:
\{\{[^}]+\}\}

API
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
reservedStrings: ['\\{\\{[^}]+\\}\\}']
});
Obfuscation'dan sonra
let _r = [`{{.Config.FeatureFlags}}`, /* … */];
Yer tutucu, çevreleyen ters tırnaklar dahil bayt bayt korunur.
Sunucu tarafı değiştirme
{{.Config.FeatureFlags}} yerine geçerli bir JSON dizesi koyun - çalışma zamanında ters tırnaklar içinde yer alacaktır
ve bunlar iç tırnak kaçışı gerektirmez:
flagsJSON, _ := json.Marshal(config.FeatureFlags) // e.g. {"newCheckout":true,"darkMode":false}
out := strings.ReplaceAll(obfuscated, "{{.Config.FeatureFlags}}", string(flagsJSON))
Çalışma zamanında: JSON.parse(`{"newCheckout":true,"darkMode":false}`) - çalışır.
Kalıp 3 - tırnaklı string yer tutucu ile reservedStrings
En uygun: ES5'te kalması gereken (şablon değişmezi olmayan) kaynak kodu veya çevreleyen API'nin normal bir string değişmezi beklediği durumlar.
Yer tutucu, tek veya çift tırnaklı bir string değişmezidir. VM obfuscation altında, JSON.stringify ile serileştirilmiş
bir JS dizisi olarak yayılan ayrılmış-dizeler dizisi üzerinden yönlendirilir - giriş tırnak stilinden bağımsız olarak
her zaman çift tırnaklı.
Kaynak
(function () {
var tags = JSON.parse("{{.Page.Tags}}");
renderTags(tags);
})();
Obfuscator seçenekleri
Arayüz
Yukarıdaki kaynaktan {{.Page.Tags}} yer tutucusunu ayırmak için, bu regex'i Reserved Strings alanına tek ters eğik
çizgilerle ekleyin. Arayüz değeri birebir saklar, bu nedenle JS kodundakinin aksine ters eğik çizgiler ikiye katlanmaz:
\{\{[^}]+\}\}

API
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
reservedStrings: ['\\{\\{[^}]+\\}\\}']
});
Obfuscation'dan sonra
var _rs = ["{{.Page.Tags}}", /* … */];
Sunucu tarafı değiştirme
Yer tutucu, çift tırnaklı bir JS dizesi içinde yer aldığından, enjekte edilen JSON yükünün içteki " karakterlerinin
\" ile kaçırılması gerekir:
raw, _ := json.Marshal(page.Tags) // e.g. ["news","tech","release"]
// Escape " for embedding inside a JS double-quoted string.
escaped := strings.ReplaceAll(string(raw), `"`, `\"`)
out := strings.ReplaceAll(obfuscated, "{{.Page.Tags}}", escaped)
Ortaya çıkan çıktı:
var _rs = ["[\"news\",\"tech\",\"release\"]", /* … */];
Çalışma zamanında: JSON.parse("[\"news\",\"tech\",\"release\"]") → ["news","tech","release"].
Kaçışı unutursanız, tarayıcı dengesiz tırnaklar görür ve bir SyntaxError fırlatır. Kalıp 2, ters tırnak kullanarak
bunu tamamen atlar.
Bir programda birden fazla yer tutucu
Üç kalıbın üçü de birlikte kullanılabilir. Bir alternasyon içeren tek bir reservedStrings regex'i, şablon motorunuzun
ürettiği her yer tutucu biçimiyle eşleşebilir:
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
reservedNames: ['^__INITIAL_STATE__$'],
reservedStrings: ['\\{\\{[^}]+\\}\\}']
});
Aynı kaynakta tanımlayıcı yer tutucularını (ham JS değerleri için) ve string yer tutucularını (oluşturulan JSON için) karıştırabilirsiniz - sunucunun gerçekte ne enjekte edeceğine göre yer tutucu başına seçim yapın.
Uyumluluk notları
- Yer tutucuları tanımlayıcılar ve dizeler arasında yeniden kullanmayın.
__TOKEN__gibi bir ayrılmış ad ve__TOKEN__ile eşleşen bir ayrılmış dize, iki farklı kod yolunu tanımlar (ayrılmış-ifadeler dizisi ile ayrılmış-dizeler dizisi). Her biri için farklı metinsel biçimler kullanın - örneğin, tanımlayıcı yer tutucuları için birUPPER_SNAKEdüzeni ve string yer tutucuları için sınırlayıcıyla sarılmış bir biçim ({{ ... }},%{...},<<<...>>>). Böylece bir regex'teki hata, diğerini sessizce eşleştiremez. reservedStringsregex'leri ham dize değerlerine karşı çalışır. Regex, kaynak metne değil, dizenin çalışma zamanı değerine karşı eşleştirilir.\{\{[^}]+\}\},{{.something}}(veya başka herhangi bir{{...}}biçimini) içeren dizelerle eşleşir. Yer tutucunuz ekstra içerikle sarılabiliyorsa ("prefix-{{.Field}}-suffix"), regex yine de eşleşir ancak dizenin tamamı korunur - değiştirmenizi buna göre planlayın.- Herhangi bir şablon motoruyla çalışır. Örnekler Go
text/templatesözdizimini kullansa da, javascript-obfuscator entegrasyonunda Go'ya özgü hiçbir şey yoktur. Obfuscator'ın çıktısı üzerinde dize düzeyinde değiştirme yapabilen her şey işe yarar: Rails ERB, Django, PHP kısa etiketleri, bir CI işlem hattındaki sed vb. Motorunuzun doğal olarak ürettiği ve gerçek JS sözdizimiyle çakışmayan sınırlayıcılar seçin.
