Почему escape_javascript перед рендерингом частичного? - PullRequest
118 голосов
/ 25 октября 2009

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

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

Для чего используется escape_javascript? 1008 *

Согласно документация Rails :

escape_javascript (JavaScript)

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

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

Ответы [ 4 ]

356 голосов
/ 26 октября 2009

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

Первая часть $("#reviews").append("<%= ... %>"); - это JavaScript с erb. Это означает, что <%= ... %> будет заменено тем, что возвращает код ruby ​​внутри него. Результатом этой замены должен быть действительный javascript, иначе он выдаст ошибку, когда клиент попытается его обработать. Итак, это первое: вам нужен действительный javascript .

Еще одна вещь, которую следует принять во внимание, это то, что генерируемый ruby ​​должен содержаться внутри строки 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>")

Привет!

8 голосов
/ 01 августа 2012

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

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

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

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

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

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

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

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

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

8 голосов
/ 25 октября 2009

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

попробуйте это:

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

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

0 голосов
/ 25 октября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...