Mengapa escape_javascript sebelum merender parsial?

120

Saya melihat episode Railscast ini dan bertanya-tanya mengapa panggilan ke escape_javascriptdiperlukan di sini:

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

Untuk apa escape_javascriptdigunakan?

Menurut dokumen Rails :

escape_javascript (javascript)

Escape carrier return dan tanda kutip tunggal dan ganda untuk segmen JavaScript.

Tapi itu tidak berarti banyak bagiku.


sumber
23
FYI, jawaban yang diterima di sini bukanlah jawaban yang benar. Kikito adalah
Steve

Jawaban:

-3

Karena Anda tidak ingin pengguna memposting JavaScript yang sebenarnya dijalankan oleh browser?

Azeem. Butt
sumber
4
Tetapi bagaimana jika Anda ingin melewatkan dan merender kode javascript?
berto77
Ya, sebenarnya ini lebih merupakan metode pemformatan. Itu tidak mencegah pengguna menjalankan javascript mereka sendiri. Tidak ada yang bisa mencegahnya.
LasagnaAndroid
3
Ini tidak membantu. Lihat jawaban kikito sebagai gantinya.
nitsas
363

Lebih mudah dipahami jika Anda membagi kode menjadi dua bagian.

Bagian pertama $("#reviews").append("<%= ... %>");adalah javascript dengan erb. Ini berarti bahwa <%= ... %>wasiat akan diganti dengan apa pun yang dikembalikan kode ruby ​​di dalamnya. Hasil dari penggantian tersebut harus berupa javascript yang valid, jika tidak maka akan terjadi error saat klien mencoba untuk memprosesnya. Jadi itu hal pertama: Anda membutuhkan javascript yang valid .

Hal lain yang perlu diperhatikan adalah bahwa apa pun yang dihasilkan ruby ​​harus terkandung di dalam string javascript dengan tanda kutip ganda - perhatikan tanda kutip ganda di sekitar <%= ... %>. Artinya, javascript yang dihasilkan akan terlihat seperti ini:

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

Sekarang mari kita periksa bagian ruby ​​di dalam file <%= ... %>. Apa yang render(:partial => @review)dilakukannya? Ini merender sebagian - yang berarti dapat merender segala jenis kode - html, css ... atau bahkan lebih banyak javascript!

Jadi, apa yang terjadi jika parsial kita berisi beberapa html sederhana, seperti ini?

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

Ingat bahwa javascript Anda menggunakan string kutip ganda sebagai parameter? Jika kita hanya mengganti <%= ... %>dengan kode parsial itu, maka kita punya masalah - segera setelah href=ada tanda kutip ganda! Javascript tidak akan valid:

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

Agar ini tidak terjadi, Anda ingin keluar dari karakter khusus ini sehingga string Anda tidak dipotong - Anda memerlukan sesuatu yang menghasilkan ini sebagai gantinya:

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

Inilah yang escape_javascriptdilakukannya. Ini memastikan bahwa string yang dikembalikan tidak akan "merusak" javascript. Jika Anda menggunakannya, Anda akan mendapatkan hasil yang diinginkan:

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

Salam!

kikito
sumber
4
memang penjelasan yang sangat bagus terima kasih. Saya kira kemudian menggunakan 'escape_javascript' agak menyesatkan karena kita sebenarnya tidak menggunakannya untuk keluar dari javascript yang sebenarnya. Anda dapat meletakkan tag script di parsial dan menjalankan javascript yang Anda inginkan.
Steve
13
@Steve setuju, nama yang lebih baik adalah escape_for_javascript, karena sering kali Anda keluar dari kode lain (html misalnya) sehingga tidak merusak javascript.
kikito
14
escape_javascript()sekarang memiliki metode yang lebih pendek: simpley j()(setidaknya di Rails 4).
mjnissim
@kikito, apakah dengan menggunakan efek ini saya mencoba membuat sebagian html yang terdiri dari bentuk jarak jauh? Saya mencoba mencari tahu mengapa merender sebagian dengan javascript yang menyertakan formulir lain yang akan dikirim melalui javascript menyebabkan permintaan kedua menjadi html, bukan js. Jika Anda punya waktu, bisakah Anda melihat pertanyaan yang sudah saya posting tentang ini? Terima kasih! Pertanyaan saya
Jake Smith
1
@JakeSmith menjawab dalam pertanyaan Anda
kikito
8

pengguna dapat memposting kode berbahaya (pengguna jahat) yang jika dibiarkan tidak lolos akan berpotensi dieksekusi, memungkinkan pengguna untuk mengontrol aplikasi Anda.

coba ini:

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

tidak terlalu akrab dengan sintaks rel, tetapi jika Anda tidak melarikan diri variablemaka kotak peringatan akan muncul, dan saya rasa itu bukan perilaku yang dimaksudkan.

barkmadley.dll
sumber
8

Jika Anda melihat sumbernya di sini , itu akan jauh lebih jelas.

Fungsi ini menyelesaikan dua hal berikut:

  1. Ini menggantikan karakter dalam string input dengan yang ditentukan di JS_ESCAPE_MAP

    Tujuannya adalah untuk memastikan bahwa kode javascript diserialkan dengan benar tanpa mengganggu string luar tempat kode tersebut disematkan. Misalnya jika Anda memiliki string javascript dalam tanda kutip ganda maka semua tanda kutip di dalam untuk string literal harus dalam tanda kutip tunggal untuk menghindari kode rusak.

  2. Fungsi tersebut juga memeriksa apakah string yang dihasilkan aman untuk html. Jika tidak maka ia melakukan pelolosan yang diperlukan untuk memastikan bahwa string menjadi html aman dan mengembalikan hasilnya.

Saat Anda menggunakan escape_javascript, ini biasanya disematkan dalam string lain atau html yang ada secara dinamis. Anda perlu memastikan bahwa melakukan ini tidak akan membuat seluruh halaman Anda tidak dirender.

Beberapa aspek dari tanggapan ini ditunjukkan dalam tanggapan lain tetapi saya ingin menyatukan semua item termasuk perbedaan antara javascript escaping dan html escaping. Selain itu, beberapa tanggapan menunjukkan bahwa fungsi ini membantu menghindari injeksi skrip. Saya rasa bukan itu tujuan dari fungsi ini. Misalnya, dalam ulasan Anda jika ulasan Anda memiliki peringatan ('halo'), hanya menambahkannya ke node tidak akan mengaktifkan pop-up. Anda tidak menyematkannya dalam fungsi yang dipicu saat pemuatan halaman atau melalui beberapa peristiwa lain. Hanya memiliki peringatan ('hi there') sebagai bagian dari html Anda tidak berarti bahwa itu akan dijalankan sebagai javascript.

Yang mengatakan saya tidak menyangkal bahwa injeksi skrip tidak mungkin dilakukan. Tapi untuk menghindari itu Anda perlu mengambil langkah-langkah saat Anda mengambil data pengguna dan menyimpannya di database Anda. Fungsi dan contoh yang Anda berikan terkait dengan rendering informasi, yang telah disimpan.

Saya harap ini membantu dan menjawab pertanyaan Anda.

Tabrez
sumber