Kısmi oluşturmadan önce neden escape_javascript?


120

Bu Railscast bölümüne bakıyorum ve escape_javascriptburada neden çağrının gerekli olduğunu merak ediyorum :

$("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>");

Ne için escape_javascriptkullanılır?

Göre Raylar docs :

escape_javascript (JavaScript)

Kaçış taşıyıcı dönüşleri ve JavaScript segmentleri için tek ve çift tırnak işaretleri.

Ama bu benim için pek bir şey ifade etmiyor.


23
Bilginize, burada kabul edilen cevap doğru cevap değil. Kikito's
Steve

Yanıtlar:


-3

Kullanıcıların tarayıcının gerçekten yürüttüğü JavaScript göndermesini istemediğiniz için mi?


4
Peki javascript kodunu ne zaman geçirmek ve oluşturmak istediğinize ne dersiniz?
berto77

Evet, aslında daha çok bir biçimlendirme yöntemi. Kullanıcıların kendi javascriptlerini çalıştırmalarını engellemez. Bunu hiçbir şey engelleyemez.
LasagnaAndroid

3
Bu yardımcı olmuyor. Bunun yerine kikito'nun cevabına bakın .
nitsas

363

Kodu ikiye bölerseniz anlamak daha kolay.

İlk bölüm $("#reviews").append("<%= ... %>"); , erb içeren javascript. Bu, <%= ... %>içindeki ruby ​​kodunun döndürdüğü şeyle değiştirileceği anlamına gelir . Bu değiştirmenin sonucu geçerli bir javascript olmalıdır, aksi takdirde istemci bunu işlemeye çalıştığında bir hata verir. İlk şey bu: geçerli bir javascript'e ihtiyacınız var .

Dikkate alınması gereken başka bir şey de Ruby'nin ürettiği her şeyin çift tırnaklı bir javascript dizgesinin içinde bulunması gerektiğidir - <%= ... %>. Bu, oluşturulan javascript'in şöyle görüneceği anlamına gelir:

$("#reviews").append("...");

Şimdi de içindeki yakut kısmını inceleyelim <%= ... %>. Nedirrender(:partial => @review) ? Bu, kısmi bir işlem yapıyor - yani her tür kodu - html, css ... veya hatta daha fazla javascript - işliyor olabilir!

Öyleyse, kısmımız bunun gibi bazı basit html içeriyorsa ne olur?

<a href="/mycontroller/myaction">Action!</a> 

JavaScript'inizin parametre olarak çift tırnaklı bir dizge aldığını hatırlıyor musunuz? Basitçe <%= ... %>bu kısmın kodunu değiştirirsek , o zaman bir sorunla karşılaşırız - href=çift ​​tırnaktan hemen sonra ! JavaScript geçerli olmayacak:

// Without escaping, you get a broken javascript string at href
$("#reviews").append("<a href="/mycontroller/myaction">Action!</a>");

Bunun olmaması için, bu özel karakterlerden kaçmak istersiniz, böylece dizeniz kesilmez - bunun yerine bunu üreten bir şeye ihtiyacınız vardır:

<a href=\"/mycontroller/myaction\">Action!</a>

Bu ne escape_javascriptyapar. Döndürülen dizenin javascript'i "kırmamasını" sağlar. Kullanırsanız, istediğiniz çıktıyı alırsınız:

$("#reviews").append("<a href=\"/mycontroller/myaction\">Action!</a>")

Saygılarımızla!


4
gerçekten çok güzel bir açıklama teşekkür ederim. Sanırım o zaman 'escape_javascript' kullanmak biraz yanıltıcı çünkü biz onu gerçek javascript'ten kaçmak için kullanmıyoruz. Kısmi bir komut dosyası etiketi koyabilir ve istediğiniz herhangi bir javascript'i çalıştırabilirsiniz.
Steve

13
@Steve, javascript'i bozmamak için escape_for_javascriptsık sık diğer kodlardan (örneğin html) kaçtığınızdan daha iyi bir ad olacağını kabul etti .
kikito

14
escape_javascript()artık daha kısa bir yönteme sahiptir: simpley j()(en azından Rails 4'te).
mjnissim

@kikito, bu etkiyi kullanmak, uzak bir formdan oluşan bir html parçasını oluşturmaya çalışmam mı? Javascript ile gönderilecek başka bir form içeren bir javascript ile kısmi bir işlemin neden ikinci isteğin js yerine html olmasına neden olduğunu bulmaya çalışıyorum. Vaktiniz varsa, bununla ilgili olarak daha önce göndermiş olduğum soruya bakar mısınız? Teşekkürler! Sorum
Jake Smith

1
@JakeSmith sorunuza cevap verdi
kikito

8

Kullanıcılar, kaçılmadan bırakıldığında potansiyel olarak yürütülecek ve kullanıcıların uygulamanızı kontrol etmesine olanak tanıyan kötü amaçlı kod (kötü niyetli kullanıcılar) gönderebilirler.

bunu dene:

<% variable = '"); alert("hi there' %>
$("#reviews").append("<%= variable %>");

rayların sözdizimine gerçekten aşina değilsiniz, ancak kaçmazsanız, variablebir uyarı kutusu gösterilecek ve bunun amaçlanan davranış olduğunu sanmıyorum.


8

Buradaki kaynağa bakarsan çok daha net olacaktır.

Bu işlev aşağıdaki iki şeyi gerçekleştirir:

  1. Giriş dizesindeki karakterleri şurada tanımlananlarla değiştirir: JS_ESCAPE_MAP'de

    Bunun amacı, javascript kodunun gömülü olduğu dış dizeye müdahale etmeden doğru şekilde serileştirildiğinden emin olmaktır. Örneğin, çift tırnak içinde bir javascript dizeniz varsa, kodun bozulmasını önlemek için dize değişmezleri için içindeki tüm tırnak işaretleri tek tırnak içinde olmalıdır.

  2. İşlev, sonuçta elde edilen dizenin html güvenli olup olmadığını da kontrol eder. Değilse, dizenin html güvenli hale geldiğinden ve sonucu döndürdüğünden emin olmak için gerekli kaçışı yapar.

Escape_javascript kullandığınızda, genellikle dinamik olarak başka bir dizeye veya mevcut html'ye gömülür. Bunu yapmanın tüm sayfanızın işlenmesini engellemeyeceğinden emin olmanız gerekir.

Bu yanıtın bazı yönleri diğer yanıtlarda belirtildi, ancak tüm öğeleri bir araya getirmek istedim, javascript kaçışı ile html kaçışı arasındaki farkı da dahil etmek istedim. Ayrıca, bazı yanıtlar bu işlevin komut dosyası yerleştirmekten kaçınmaya yardımcı olduğunu ima eder. Bu işlevin amacının bu olduğunu sanmıyorum. Örneğin, incelemenizde eğer incelemenizde uyarı varsa ('merhaba'), onu düğüme eklemek pop-up'ı tetiklemeyecektir. Bunu, sayfa yüklemede veya başka bir olayda tetiklenen bir işlevin içine yerleştirmiyorsunuz. Html'nizin bir parçası olarak yalnızca uyarı ('merhaba') olması, javascript olarak çalışacağı anlamına gelmez.

Bununla birlikte, komut dosyası yerleştirmenin mümkün olmadığını inkar etmiyorum. Ancak bunu önlemek için kullanıcı verilerini alırken ve veri tabanınızda saklarken adımlar atmanız gerekir. Sağladığınız işlev ve örnek, önceden kaydedilmiş olan bilgilerin işlenmesi ile ilgilidir.

Umarım bu yardımcı olur ve sorunuzu yanıtlar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.