Чому escape_javascript перед тим, як зробити частковим?


120

Я переглядаю цей епізод Railscast і цікавлюсь, для чого escape_javascriptтут потрібен заклик :

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

Для чого escape_javascriptвикористовується?

Згідно з документами Rails :

escape_javascript (javascript)

Повернення оператора операційного обслуговування та єдині та подвійні котирування для сегментів JavaScript.

Але це для мене мало значить.


23
FYI, прийнята відповідь тут не є правильною відповіддю. Кікіто
Стів

Відповіді:


-3

Тому що ви не хочете, щоб користувачі розміщували JavaScript, який браузер насправді виконує?


4
А як щодо того, коли ви хочете передати та віддати код JavaScript?
berto77

Так, насправді це більше метод форматування. Це не заважає користувачам виконувати свій власний JavaScript. Ніщо не може цього завадити.
LasagnaAndroid

3
Це не корисно. Дивіться замість відповіді kikito .
nitsas

363

Це легше зрозуміти, якщо ви розділите код на дві частини.

Перша частина $("#reviews").append("<%= ... %>");- javascript з erb. Це означає, що <%= ... %>заміна буде замінена тим, чим повернеться рубіновий код всередині неї. Результатом цієї заміни повинен бути дійсний javascript, інакше він видасть помилку, коли клієнт намагається його обробити. Тож це перше: вам потрібен дійсний JavaScript .

Інша річ, яку слід врахувати, полягає в тому, що все, що генерує рубін, має міститись у рядку javascript з подвійними лапками - помічайте подвійні лапки навколо <%= ... %>. Це означає, що створений javascript буде виглядати приблизно так:

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

Тепер розглянемо рубінову частину всередині <%= ... %>. Що робить render(:partial => @review)? Це візуалізація часткова - це означає, що це може бути візуалізація будь-якого коду - html, css ... або навіть більше JavaScript!

Отже, що станеться, якщо наш частковий містить якийсь простий html, як цей?

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

Пам'ятайте, що ваш JavaScript приймав за параметр рядок з двома цитатами? Якщо ми просто замінимо <%= ... %>кодом цього часткового, тоді у нас виникає проблема - одразу після того href=, як з’явиться подвійна цитата! JavaScript не буде дійсним:

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

Щоб цього не сталося, ви хочете уникнути цих спеціальних символів, щоб ваш рядок не був розрізаний - вам потрібно щось, що генерує це замість цього:

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

Це те, що escape_javascriptробить. Це гарантує, що повернута рядок не "зламає" JavaScript. Якщо ви його використовуєте, ви отримаєте бажаний вихід:

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

З повагою!


4
дійсно, дуже приємне пояснення дякую. Я думаю, що використання 'escape_javascript' є деяким оманом, оскільки ми насправді не використовуємо його для виходу з фактичного JavaScript. Ви можете помістити тег сценарію в частковий і виконати будь-який javascript, який ви хочете.
Стів

13
@Steve погодився, краще ім'я буде escape_for_javascript, оскільки часто ви уникаєте іншого коду (наприклад, html), щоб він не порушував JavaScript.
кікіто

14
escape_javascript()тепер є коротший метод: просто j()(принаймні в Rails 4).
mjnissim

@kikito, чи використовуючи цей ефект, я намагаюся зробити html частковою, що складається з віддаленої форми? Я намагаюся з’ясувати, чому надання часткового з javascript, який включає іншу форму, яка буде подана через javascript, викликає, що другий запит буде html замість js. Якщо у вас є час, ви можете, будь ласка, подивитись на питання, яке я вже розміщував щодо цього? Дякую! Моє запитання
Джейк Сміт

1
@JakeSmith відповів на ваше запитання
kikito

8

користувачі можуть розміщувати шкідливий код (зловмисні користувачі), які, якщо їх не буде розроблено, потенційно можуть бути виконані, що дозволяє користувачам контролювати вашу програму.

спробуйте це:

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

насправді не знайомий із синтаксисом рейок, але якщо ви не уникнете, variableто з’явиться вікно попередження, і я не думаю, що це призначена поведінка.


8

Якщо ви подивитесь на джерело тут , це буде набагато зрозуміліше.

Ця функція виконує наступні дві речі:

  1. Він замінює символи в рядку введення тими, які визначені в JS_ESCAPE_MAP

    Мета цього - переконатися, що код javascript правильно серіалізується, не втручаючись у зовнішню рядок, в який він вбудований. Наприклад, якщо у вас є рядок javascript у подвійних лапках, то всі цитати для рядкових літералів повинні бути в одиничних лапках, щоб уникнути порушення коду.

  2. Функція також перевіряє, чи отриманий рядок є html-безпечним. Якщо це не так, він виконує необхідне проходження, щоб переконатися, що рядок стає html безпечним і повертає результат.

Коли ви використовуєте escape_javascript, він зазвичай динамічно вбудовується в інший рядок або існуючий html. Вам потрібно переконатися, що це не призведе до відображення всієї вашої сторінки.

Деякі аспекти цієї відповіді були вказані в інших відповідях, але я хотів об'єднати всі елементи, включаючи різницю між відключенням JavaScript та втечею html. Також деякі відповіді натякають на те, що ця функція допомагає уникнути введення сценарію. Я не думаю, що це мета цієї функції. Наприклад, у вашому огляді, якщо у вашому огляді є попередження ("привіт, там"), просто додавання його до вузла не відкриє спливаюче вікно. Ви не вбудовуєте його у функцію, яка запускається під час завантаження сторінки або через якусь іншу подію. Тільки те, що попередження ("привіт там") як частина вашого html не означає, що воно буде виконуватися як JavaScript.

Це сказало, що я не заперечую, що введення сценарію неможливо. Але щоб уникнути того, що вам потрібно вжити заходів, коли ви берете дані користувача та зберігаєте їх у своїй базі даних. Функція та приклад, які ви надаєте, пов'язані з наданням інформації, яка вже була збережена.

Я сподіваюся, що це допоможе і відповість на ваше запитання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.