Исключение HTML-объектов в строковых литералах JavaScript в блоке <script>
С одной стороны, если у меня есть
<script>
var s = 'Hello </script>';
console.log(s);
</script>
браузер рано разорвет блок <script>
, и в основном я получаю эту страницу.
С другой стороны, значение строки может исходить от пользователя (скажем, через ранее представленную форму, и теперь строка заканчивается вставкой в блок <script>
в качестве литерала), поэтому вы можете ожидать все в этой строке, включая злонамеренно созданные теги. Теперь, если я удаляю строковый литерал с помощью htmlentities() при создании страницы, значение s будет содержать экранированные объекты буквально, то есть s будет выводить
Hello </script>
что не является желательным поведением в этом случае.
Одним из способов правильного экранирования строк JS в блоке <script>
является экранирование косой черты, если оно следует за левой угловой скобкой или просто всегда выходит из косой черты, т.е.
var s = 'Hello <\/script>';
Кажется, что это нормально работает.
Затем возникает вопрос о JS-коде в обработчиках событий HTML, который также можно легко сломать, например.
<div onClick="alert('Hello ">')"></div>
выглядит действительным сначала, но ломается в большинстве (или всех?) браузеров. Это, очевидно, требует полной кодировки сущности HTML.
Мой вопрос: какова лучшая/стандартная практика для надлежащего покрытия всех вышеперечисленных ситуаций - то есть JS в блоке script, JS в обработчиках событий - если ваш JS-код частично может быть сгенерирован на стороне сервера и может потенциально могут содержать вредоносные данные?
Ответы
Ответ 1
Следующие символы могут помешать работе с парсером HTML или Javascript и должны быть экранированы в строковых литералах: <, >, ", ', \,
и &
.
В блоке script с использованием escape-символа, как вы выяснили, работает. Метод конкатенации (</scr' + 'ipt>'
) может быть трудно читаемым.
var s = 'Hello <\/script>';
Для встроенного Javascript в HTML вы можете использовать объекты:
<div onClick="alert('Hello ">')">click me</div>
Демо: http://jsfiddle.net/ThinkingStiff/67RZH/
Метод, который работает как в блоках <script>
, так и в встроенном Javascript, \uxxxx
, где xxxx
- шестнадцатеричный код символа.
-
<
- \u003c
-
>
- \u003e
-
"
- \u0022
-
'
- \u0027
-
\
- \u005c
-
&
- \u0026
Демо: http://jsfiddle.net/ThinkingStiff/Vz8n7/
HTML:
<div onClick="alert('Hello \u0022>')">click me</div>
<script>
var s = 'Hello \u003c/script\u003e';
alert( s );
</script>
Ответ 2
(отредактируйте - как-то не заметили, что вы уже упомянули слэш-побег в своем вопросе уже...)
ОК, чтобы вы знали, как избежать косой черты.
В встроенных обработчиках событий вы не можете использовать ограничивающий символ внутри литерала, поэтому используйте другой:
<div onClick='alert("Hello \"")'>test</div>
Но это все помогает твоей жизни. Просто не используйте встроенные обработчики событий! Или, если вам абсолютно необходимо, попросите их вызвать функцию, определенную в другом месте.
Вообще говоря, есть несколько причин, по которым ваш серверный код должен писать javascript. Не создавайте сценарии с сервера - передавайте данные в предварительно написанные сценарии.
(оригинал)
Вы можете избежать чего-либо в строковом литерале JS с обратным слэшем (это иначе не специальный escape-символ):
var s = 'Hello <\/script>';
Это также оказывает положительное влияние на то, чтобы не интерпретировать его как html. Таким образом, вы можете сделать замену одеяла "/" на "\/", чтобы не повредить эффект.
В целом, однако, я обеспокоен тем, что у вас будут данные, представленные пользователем, как строковый литерал в javascript. Вы генерируете код javascript на сервере? Почему бы просто не передавать данные как JSON или атрибут "данные" HTML или что-то вместо этого?
Ответ 3
Я бы сказал, что лучше всего избегать встроенного JS.
Поместите JS-код в отдельный файл и включите его с атрибутом src
<script src="path/to/file.js"></script>
и использовать его для установки обработчиков событий изнутри isntead для размещения этих в HTML.
//jquery example
$('div.something').on('click', function(){
alert('Hello>');
})
Ответ 4
Вот как я это делаю:
function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}
var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';
test.value=encode(myString);
testing.innerHTML=encode(myString);
/*************
* \x26 is &ersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>
<div id="testing">www.WHAK.com</div>
Ответ 5
Большинство людей используют этот трюк:
var s = 'Hello </scr' + 'ipt>';