2009-10-25 3 views
110

Я смотрю на this Railscast episode и интересно, почему вызов escape_javascript нужен здесь:Почему escape_javascript перед рендерингом частичного?

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

Что escape_javascript используется?

По the Rails docs:

escape_javascript (JavaScript)

побег несущей возвращается и одиночные и двойные кавычки для сегментов JavaScript.

Но это не значит для меня ничего.

+19

FYI, принятый ответ здесь не правильный ответ. Kikito's is – Steve

ответ

1

Потому что вы не хотите, чтобы пользователи отправляли JavaScript, что браузер действительно выполняет?

+4

Но как насчет того, когда вы хотите передать и обработать javascript-код? – berto77

+0

Да, на самом деле это скорее метод форматирования.Это не мешает пользователям выполнять свой собственный javascript. Ничто не может этого предотвратить. – Deviljho

+2

Это не полезно. См. [Ответ kikito] (http://stackoverflow.com/a/1623813/703233). – nitsas

8

Пользователи могут оставлять за собой вредоносный код (злонамеренные пользователи), который, если оставить его незанятым, потенциально может быть выполнен, что позволит пользователям управлять вашим приложением.

попробовать это:

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

не очень знакомы с синтаксисом рельсам, но если вы не избежать variable тогда окно предупреждения покажет, и я не думаю, что это предназначено поведение.

327

Это легче понять, если вы разделите код на две части.

Первая часть $("#reviews").append("<%= ... %>"); - это javascript с erb. Это означает, что <%= ... %> будет заменен тем, что возвращает код Ruby внутри него. Результатом этой замены должен быть действительный 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, который вы хотите. – Steve

+12

@Steve согласился, лучшим именем будет 'escape_for_javascript', так как часто вы избегаете другого кода (например, html), чтобы он не разбивал javascript. – kikito

+13

'escape_javascript()' теперь имеет более короткий метод: simpley 'j()' (по крайней мере, в Rails 4). – mjnissim

7

Если вы посмотрите на источник here, это будет намного понятнее.

Эта функция выполняет следующие две вещи:

  1. Он заменяет символы во входной строке с теми , определенных в JS_ESCAPE_MAP

    Целью этого является, чтобы убедиться, что Javascript код сериализован правильно, не мешая внешней строке , внутри которой он встроен. Например, если в двойных кавычках есть строка javascript , то все кавычки в пределах для строковых литералов должны быть в одинарных кавычках, чтобы избежать кода от .

  2. Функция также проверяет, является ли результирующая строка html безопасной. Если это не так, он делает необходимое экранирование, чтобы убедиться, что строка становится html безопасной и возвращает результат.

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

Некоторые аспекты этого ответа были указаны в других ответах, но я хотел собрать все элементы вместе, включая разницу между экранированием javascript и экранированием html. Кроме того, в некоторых ответах говорится, что эта функция помогает избежать инъекции скрипта. Я не думаю, что это цель этой функции. Например, в вашем обзоре, если в вашем отзыве есть предупреждение («привет там»), просто добавление его к узлу не приведет к всплытию. Вы не встраиваете его в функцию, которая запускается при загрузке страницы или через какое-то другое событие. Простое оповещение («привет там») как часть вашего html не означает, что он будет выполняться как javascript.

Это говорит, что я не отрицаю, что инъекция сценария невозможна. Но чтобы избежать этого, вам нужно предпринять шаги, когда вы берете пользовательские данные и храните их в своей базе данных. Функция и пример, которые вы предоставляете, связаны с предоставлением информации, которая уже была сохранена.

Надеюсь, это поможет и ответит на ваш вопрос.

-3

Он не будет выполнять javascript того, что вы визуализируете

Смежные вопросы