Как проще всего закодировать строку PHP для вывода в переменную JavaScript?
У меня есть строка PHP, которая включает кавычки и новые строки. Мне нужно, чтобы содержимое этой строки было помещено в переменную JavaScript.
Обычно я просто создаю свой JavaScript в файле PHP, а ля:
<script>
var myvar = "<?php echo $myVarValue;?>";
</script>
Однако это не работает, если $myVarValue содержит кавычки или символы новой строки.






закодируйте его с помощью JSON
Вероятно, самый простой способ заставить это работать 100% времени. Слишком много случаев, чтобы рассматривать их иначе.
Json работает только с кодировкой UTF-8. Так что это не решение, если ваш сайт работает в кодировке, отличной от UTF-8.
@nir: с одной стороны, я не знаю причин использовать любую другую кодировку, с другой стороны, полный кодировщик JSON также управляет любым необходимым преобразованием кодировки
Кодирования с помощью JSON недостаточно, вы также должны убедиться, что любая строка Javascript, содержащая </script> (без учета регистра), обрабатывается правильно.
Единственное, что меня беспокоит, так это то, что кодирование с помощью json заставит его преобразовать в объект. На практике это легче понять, но когда вы дойдете до сложных массивов данных, в частности, для чтения результатов SQL из базы данных, программисту потребуется более глубокое знание javascript для эффективной обработки данных. По сути, я говорю, что пример сценария использования был бы отличным.
Кодирование одного скалярного значения с помощью JSON не приведет к принудительному преобразованию его к объекту - вы просто получите строку utf-8. Например, ваш php-код выглядит так: $ x = "<script> alert ('xss!'); </script>"; и ваш HTML-код выглядит так: <script> var x = <? = json_encode ($ x);?> </script> результат при просмотре будет: <script> var x = "<script> alert ('xss ! '); <\ / script> "</script> Обратите внимание на двойные кавычки и экранированную косую черту.
Если вы используете шаблонизатор для создания своего HTML-кода, вы можете заполнить его чем угодно!
Проверьте XTemplates. Это приятный, легкий, шаблонный движок с открытым исходным кодом.
Ваш HTML / JS будет выглядеть так:
<script>
var myvar = {$MyVarValue};
</script>
htmlspecialchars
Описание
string htmlspecialchars ( string $string [, int $quote_style [, string $charset [, bool $double_encode ]]] )
Некоторые символы имеют особое значение в HTML и должны быть представлены объектами HTML, если они хотят сохранить свое значение. Эта функция возвращает строку с некоторыми из этих преобразований; сделанные переводы наиболее полезны для повседневного веб-программирования. Если вам нужно перевести все символы HTML, используйте вместо этого htmlentities ().
Эта функция полезна для предотвращения того, чтобы вводимый пользователем текст содержал разметку HTML, например, в доске сообщений или в приложении гостевой книги.
Выполненные переводы:
* '&' (ampersand) becomes '&'
* '"' (double quote) becomes '"' when ENT_NOQUOTES is not set.
* ''' (single quote) becomes ''' only when ENT_QUOTES is set.
* '<' (less than) becomes '<'
* '>' (greater than) becomes '>'
http://ca.php.net/htmlspecialchars
Это будет правильным решением только в том случае, если содержимое переменной JS действительно должно быть HTML, где строковый токен, например & amp; имеет значение. В противном случае лучше не преобразовывать их в сущности.
function escapeJavaScriptText($string)
{
return str_replace("\n", '\n', str_replace('"', '\"', addcslashes(str_replace("\r", '', (string)$string), "\0..\37'\\")));
}
Мне это было нужно, потому что я использовал содержимое переменной как часть конкатенированного выражения javascript.
Это мне действительно помогло.
Вы можете вставить его в скрытый DIV, а затем назначить innerHTML DIV вашей переменной JavaScript. Вам не нужно беспокоиться о том, чтобы от чего-либо сбежать Только убедитесь, что не поместили туда сломанный HTML.
"не помещать туда сломанный HTML", это означает экранирование "сущностей HTML" (по крайней мере, "<" и "&")
Нет, просто не закрывайте контейнер DIV раньше времени.
Вы могли бы попробовать
<script type = "text/javascript">
myvar = unescape('<?=rawurlencode($myvar)?>');
</script>
Не работает полностью. Попробуйте с этой строкой ::: Мне интересно "эй, джуд", потому что 1 + 1 <5 ::: мы все еще получаем & lt; так что не 100% двунаправленная транслитерация
unescape устарел. Вместо этого используйте decodeURIComponent.
Расширяя чужой ответ:
<script>
var myvar = <?php echo json_encode($myVarValue); ?>;
</script>
Для использования json_encode () требуется:
$myVarValue в кодировке UTF-8 (или, конечно, US-ASCII)Поскольку UTF-8 поддерживает полный Unicode, преобразование на лету должно быть безопасным.
Обратите внимание: поскольку json_encode избегает косых черт, даже строка, содержащая </script>, будет безопасно экранирована для печати с блоком сценария.
Если вы используете UTF-8, это, безусловно, лучшее решение.
Важно, чтобы при реализации json_encode не использовалась косая черта. В противном случае это не сработало бы, если бы $ myVarValue был "</script>". Но json_encode избегает косых черт, так что все в порядке.
Если вы не 5.2, попробуйте jsonwrapper с сайта boutell.com boutell.com/scripts/jsonwrapper.html
Если вы используете это в переносимом (например, библиотечном) коде, есть одно предостережение. json_encode () был сообщается как сломанный. У меня это исправлено (5.4.4-7 в debian), но я не знаю о более ранних версиях.
Имейте в виду, что в PHP 5.3 теперь есть опции для экранирования различных символов. См. Пример № 2 для различных выходов: php.net/manual/en/function.json-encode.php
Обратите внимание, что если вы используете это в атрибутах onclick и т. П., Вам необходимо передать результат json_encode в htmlspecialchars, например: htmlspecialchars(json_encode($string),ENT_QUOTES,'utf-8'), иначе у вас могут возникнуть проблемы, например, с &bar; в foo()&&bar;, который интерпретируется как объект HTML. .
Сработало большое спасибо! Также, чтобы другие не столкнулись с тем же, что и я, при использовании этого: убедитесь, что вы удалили кавычки вокруг переменных json_encoded php, которые вы вставляете в javascript, потому что json_encode уже включает их.
Если строка содержит новую строку, я думаю, она выдаст ошибку
Простой вызов json_encode () для экранирования вывода небезопасен. Добавление JSON_HEX_QUOT | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_TAG в качестве второго параметра помогает в некоторых случаях, но он все же позволяет вам вводить некоторый код JS, например «1; alert (10)» или что-то более опасное в примере, подобном этому. Помимо правильной проверки ввода, я не уверен, что может помочь в этом случае. Без второго параметра внедрение любого кода тривиально.
Я считаю, что в PHP 5.4+ лучше всего использовать два хороших специальных флага. И, конечно же, короткий синтаксис. Вот он: var myvar = <?=json_encode($myVarValue, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE)?>;. Первый говорит не кодировать косую черту /, второй печатает любые символы utf8 не как xNNNN, а как есть.
@FlameStorm: кодирует косую черту, что полезно для предотвращения инъекций </script> (!!), поскольку они становятся </script>. В противном случае тег скрипта закрывается преждевременно, что может быть использовано как часть атаки. - см. также предыдущий комментарий stackoverflow.com/questions/168214/…
@hakre: Но как строка PHP, содержащая "...</script>...", может стать нестроковой JS </script> вместо просто строки JS "...</script>..." после json_encode PHP? Он всегда добавляет кавычки для строки. Итак, var x = "...</script>..."; - это просто строка JS. Без перерыва.
Для тех, кто использует Laravel, вы можете использовать ультра-простой @json($myVarValue). См. «Отрисовка JSON» в разделе laravel.com/docs/5.6/blade#displaying-data.
Есть крайние случаи, когда json_encode () недостаточно: docs.zendframework.com/zend-escaper/escaping-javascript
привет, пожалуйста, кто-нибудь знает, почему я получаю SyntaxError: expected expression, got '<' при использовании var a = <?php echo json_encode($_REQUEST["errors"]); ?>;, спасибо
У меня была аналогичная проблема, и я понимаю, что следующее - лучшее решение:
<script>
var myvar = decodeURIComponent("<?php echo rawurlencode($myVarValue); ?>");
</script>
Однако связь, опубликованный micahwittman, предполагает, что есть некоторые незначительные различия в кодировке. Предполагается, что функция PHP rawurlencode() соответствует RFC 1738, в то время как, похоже, не было таких усилий с decodeURIComponent() Javascript.
Я считаю, что decodeURIComponent соответствует RFC 3986.
Это правильное решение, когда вы разбираете большие строки (например, содержимое html как строку)
@RaduGheorghies Почему?
Приведенное ниже решение Micah сработало для меня, поскольку сайт, который мне пришлось настраивать, не был в UTF-8, поэтому я не мог использовать json; Я бы проголосовал за это, но моя репутация недостаточно высока.
function escapeJavaScriptText($string)
{
return str_replace("\n", '\n', str_replace('"', '\"', addcslashes(str_replace("\r", '', (string)$string), "\0..\37'\\")));
}
Я тоже! Эти две строки кода - лучшее, что случилось с php (по крайней мере, IMHO). Большое спасибо!!
Я не уверен, что это плохая практика или нет, но моя команда и я использовали смешанное решение html, JS и php. Мы начинаем со строки PHP, которую хотим вставить в переменную JS, давайте назовем ее:
$someString
Затем мы используем скрытые элементы формы на странице и устанавливаем их значение в виде строки:
<form id = "pagePhpVars" method = "post">
<input type = "hidden" name = "phpString1" id = "phpString1" value = "'.$someString.'" />
</form>
Тогда это простой вопрос определения JS var через document.getElementById:
<script type = "text/javascript" charset = "UTF-8">
var moonUnitAlpha = document.getElementById('phpString1').value;
</script>
Теперь вы можете использовать переменную JS "moonUnitAlpha" везде, где хотите получить это строковое значение PHP. Похоже, это действительно хорошо работает для нас. Посмотрим, выдержит ли он интенсивное использование.
Я делал это в своих предыдущих проектах. В следующий раз я попробую использовать данные jQuery.
не забудьте htmlencode ваш $ someString ... и хотя это нормально для input @ value, вы должны быть особенно осторожны с атрибутами типа href / src / onclick (попробуйте белый список), так как они могут сразу перейти к использованию javascript : протокол, от которого не защищены значения в кодировке html.
На всякий случай вам действительно стоит сделать value = "<?php echo htmlspecialchars(json_encode($someString));?>".
Параноидальная версия: Экранирование каждого символа.
function javascript_escape($str) {
$new_str = '';
$str_len = strlen($str);
for($i = 0; $i < $str_len; $i++) {
$new_str .= '\x' . sprintf('%02x', ord(substr($str, $i, 1)));
}
return $new_str;
}
Обновлено: Причина, по которой json_encode() может не подходить, заключается в том, что иногда вам нужно предотвратить создание ", например
<div onclick = "alert(???)" />
У меня сработало экранирование каждого персонажа. json_encode не очень хорошо обрабатывает обратную косую черту. Если вам нужно передать что-то вроде регулярного выражения из mysql в javascript в качестве параметра, то это лучший способ.
@ kristoffer-ryhl правильно отмечает, что dechex не работает для '\ t' (= '\ x08'), поэтому я отредактировал его, чтобы использовать sprintf. Однако это все еще не работает для символов UTF-8 (вместо этого потребуется использовать '\ u') ...
Для атрибута HTML вы можете сделать <div onclick = "alert(<?php echo htmlspecialchars(json_encode($var));?>" />
Это не сохранение в Юникоде, проверьте это: docs.laminas.dev/laminas-escaper/escaping-javascript
Не запускайте его через addslashes(); если вы находитесь в контексте HTML-страницы, анализатор HTML все еще может видеть тег </script>, даже в середине строки, и предполагать, что это конец JavaScript:
<?php
$value = 'XXX</script><script>alert(document.cookie);</script>';
?>
<script type = "text/javascript">
var foo = <?= json_encode($value) ?>; // Use this
var foo = '<?= addslashes($value) ?>'; // Avoid, allows XSS!
</script>
Возможно, я делаю глупую ошибку, но когда я пытаюсь выполнить этот код, я получаю следующую консольную ошибку SyntaxError: expected expression, got '<' ТОЛЬКО, когда я ссылаюсь на внешний файл .js, когда он inilne, он работает нормально. Мысли?
@RADMKT Просто предположение, но если это файл .js, он, вероятно, не использует PHP. Возможно, стоит загрузить внешний файл JS в веб-браузере, чтобы увидеть вывод кода.
<script>
var myVar = <?php echo json_encode($myVarValue); ?>;
</script>
или же
<script>
var myVar = <?= json_encode($myVarValue) ?>;
</script>
Вы не должны заключать закодированное значение в кавычки.
Обратите внимание, что json_encode избегает косых черт, что означает, что он никогда не напечатает </script> случайно.
Не надо. Используйте Ajax, поместите его в атрибуты data-* вашего HTML или что-нибудь еще значимое. Использование встроенных скриптов увеличивает размер ваших страниц и может быть небезопасным или по-прежнему позволять пользователям испортить макет, если…
… Вы делаете более безопасную функцию:
function inline_json_encode($obj) {
return str_replace('<!--', '<\!--', json_encode($obj));
}
Я почти уверен, что <!-- не нужно экранировать в блоке сценария, единственное, на что вам нужно обратить внимание в допустимом строковом литерале Javascript, - это </script>, а json_encode никогда не выводит это, потому что он избегает косых черт.
@Flimm: Вы смотрели ссылку на кодовую панель? Попробуйте <script>console.info("<!--<script>")</script><script>console.log(")/;alert('execute arbitrary code here');<!---->")</script>, где две строки, переданные в console.info, предоставляются пользователем (т. Е. Шаблон выглядит как <script>console.info({{ s1 }})</script><script>console.info({{ s2 }})</script>, где $s1 и $s2 поступают из плохого кодировщика JSON). Конечно, вторая строка содержит неэкранированную косую черту, и пример полностью надуманный, но злоумышленник все равно может вызвать синтаксическую ошибку, подобную этой.
@Flimm: Как это работает: <!--<script> заставляет законный </script> обрабатываться как код, а не как конечный тег.
Просто хотел указать, что вы можете использовать
utf8_encode()перед передачей строки вjson_encode. Вот что я делаю:echo json_encode(utf8_encode($msg));