Как мне избежать строки внутри кода JavaScript внутри обработчика onClick? - PullRequest
63 голосов
/ 19 сентября 2008

Может быть, я просто слишком обдумывал это, но у меня возникла проблема с выяснением того, что можно использовать в строке в некотором коде JavaScript внутри обработчика ссылки onClick. Пример:

<a href="#" onclick="SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;">Select</a>

В <%itemid%> и <%itemname%> происходит замена шаблона. Моя проблема в том, что имя элемента может содержать любой символ, включая одинарные и двойные кавычки. В настоящее время, если он содержит одинарные кавычки, он нарушает код JavaScript.

Моей первой мыслью было использование функции языка шаблонов для JavaScript-экранирования имени элемента, которое просто экранирует кавычки. Это не исправит случай строки, содержащей двойные кавычки, которая нарушает HTML-код ссылки. Как обычно решается эта проблема? Нужно ли HTML-экранировать весь обработчик onClick?

Если это так, то это выглядело бы действительно странно, поскольку функция escape для языка шаблонов также HTMLify скобок, кавычек и точек с запятой ...

Эта ссылка создается для каждого результата на странице результатов поиска, поэтому создание отдельного метода внутри тега JavaScript невозможно, поскольку мне нужно сгенерировать его для каждого результата.

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

Ответы [ 13 ]

77 голосов
/ 19 сентября 2008

В JavaScript вы можете кодировать одинарные кавычки как "\ x27" и двойные кавычки как "\ x22". Следовательно, с помощью этого метода вы можете, как только вы попадете в (двойные или одинарные) кавычки строкового литерала JavaScript, безнаказанно использовать \ x27 \ x22, не опасаясь, что любые встроенные кавычки «вырвутся» из вашей строки.

\ xXX для символов <127 и \ uXXXX для <a href="http://en.wikipedia.org/wiki/Unicode" rel="noreferrer"> Unicode , поэтому, вооружившись этими знаниями, вы можете создать надежную функцию JSEncode для всех символов, которые выходят за рамки обычного Белый список.

Например,

<a href="#" onclick="SelectSurveyItem('<% JSEncode(itemid) %>', '<% JSEncode(itemname) %>'); return false;">Select</a>
20 голосов
/ 23 декабря 2011

В зависимости от языка на стороне сервера, вы можете использовать один из них:

.NET 4.0

string result = System.Web.HttpUtility.JavaScriptStringEncode("jsString")

Java

import org.apache.commons.lang.StringEscapeUtils;
...

String result = StringEscapeUtils.escapeJavaScript(jsString);

Python

import json
result = json.dumps(jsString)

PHP

$result = strtr($jsString, array('\\' => '\\\\', "'" => "\\'", '"' => '\\"', 
                                 "\r" => '\\r', "\n" => '\\n' ));

Ruby on Rails

<%= escape_javascript(jsString) %>
10 голосов
/ 03 февраля 2009

Используйте скрытые интервалы, по одному для каждого из параметров <%itemid%> и <%itemname%> и запишите их значения внутри них.

Например, диапазон для <%itemid%> будет выглядеть как <span id='itemid' style='display:none'><%itemid%></span>, а в функции javascript SelectSurveyItem для выбора аргументов из этих диапазонов innerHTML.

9 голосов
/ 19 сентября 2008

Старайтесь не использовать строковые литералы в своем HTML и используйте JavaScript для привязки событий JavaScript.

Кроме того, избегайте 'href = #', если вы действительно не знаете, что делаете. Это нарушает юзабилити для навязчивых щелчков мышью (открыватель вкладок).

<a id="tehbutton" href="somewhereToGoWithoutWorkingJavascript.com">Select</a>

Моя библиотека JavaScript на выбор - jQuery:

<script type="text/javascript">//<!-- <![CDATA[
jQuery(function($){
   $("#tehbutton").click(function(){
        SelectSurveyItem('<%itemid%>', '<%itemname%>');
        return false;
   });
});
//]]>--></script>

Если вы случайно выводите список таких ссылок, вы можете сделать это:

<a id="link_1" href="foo">Bar</a>
<a id="link_2" href="foo2">Baz</a>

<script type="text/javascript">
   jQuery(function($){
        var l = [[1,'Bar'],[2,'Baz']];
        $(l).each(function(k,v){
           $("#link_" + v[0] ).click(function(){
                SelectSurveyItem(v[0],v[1]);
                return false;
           });
        });
   });
 </script>
8 голосов
/ 19 сентября 2008

Если он входит в атрибут HTML, вам потребуется как HTML-кодировать (как минимум: > до &gt; < до &lt и " до &quot;), и экранируют одинарные кавычки (с обратной косой чертой), чтобы они не мешали вашему цитированию javascript.

Лучший способ сделать это с вашей системой шаблонов (расширить ее, если необходимо), но вы могли бы просто создать пару функций экранирования / кодирования и обернуть их обе вокруг любых данных, которые там находятся.

И да, совершенно правильно (даже верно) HTML-экранировать все содержимое ваших атрибутов HTML, даже если они содержат javascript.

3 голосов
/ 19 сентября 2008

Другим интересным решением может быть сделать это:

<a href="#" itemid="<%itemid%>" itemname="<%itemname%>" onclick="SelectSurveyItem(this.itemid, this.itemname); return false;">Select</a>

Тогда вы можете использовать стандартную HTML-кодировку для обеих переменных, не беспокоясь о дополнительных сложностях цитирования javascript.

Да, создает HTML, который строго недопустим. Тем не менее, является допустимым методом, и все современные браузеры поддерживают его.

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

1 голос
/ 16 февраля 2012

Я тоже сталкивался с этой проблемой. Я создал скрипт для преобразования одинарных кавычек в экранированные двойные, которые не нарушат HTML.

function noQuote(text)
{
    var newtext = "";
    for (var i = 0; i < text.length; i++) {
        if (text[i] == "'") {
            newtext += "\"";
        }
        else {
            newtext += text[i];
        }
    }
    return newtext;
}
1 голос
/ 19 сентября 2008

Во-первых, было бы проще, если бы обработчик onclick был установлен следующим образом:

<a id="someLinkId"href="#">Select</a>
<script type="text/javascript">
  document.getElementById("someLinkId").onClick = 
   function() {
      SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;
    };

</script>

Затем для JavaScript необходимо экранировать itemid и itemname (то есть " становится \" и т. Д.).

Если вы используете Java на стороне сервера, вы можете взглянуть на класс StringEscapeUtils из общего языка Джакарты. В противном случае, это не должно занять слишком много времени, чтобы написать свой собственный метод escapeJavascript.

1 голос
/ 19 сентября 2008

Используйте библиотеку Microsoft Anti-XSS , которая включает кодирование JavaScript.

1 голос
/ 19 сентября 2008

Объявите отдельные функции в разделе и вызовите их в вашем методе onClick. Если у вас есть лоты, вы можете использовать схему именования, которая нумерует их, или передать целое число в ваших onClicks и иметь большой жирный оператор переключения в функции.

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