Ucieczka cytatów w JavaScript


211

Generuję wartości z bazy danych (tak naprawdę nie jest otwarta na publiczne wejście, ale jest otwarta na wejście dla użytkownika w firmie - co oznacza, że ​​nie martwię się o XSS ).

Próbuję wygenerować taki tag:

<a href="" onclick="DoEdit('DESCRIPTION');">Click Me</a>

OPIS to tak naprawdę wartość z bazy danych, która wygląda mniej więcej tak:

Prelim Assess "Mini" Report

Próbowałem zamienić „na \”, ale bez względu na to, co próbuję, Firefox przerywa moje wywołanie JavaScript po spacji po słowie Assess i powoduje wiele problemów.

Muszę odmówić oczywistej odpowiedzi, ale nie potrafię tego rozgryźć przez całe życie.

Czy ktoś chciałby zwrócić uwagę na moją idiotyzm?

Oto cała strona HTML (ostatecznie będzie to strona ASP.NET , ale aby to rozwiązać, wyjąłem wszystko inne oprócz kodu problemu)

<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment \"Mini\"'); return false;">edit</a>
    </body>
</html>

3
Dobrym pomysłem jest, aby onclickzałącznik do wydarzenia był dyskretny i przenieść wszystkie informacje z bazy danych na wyspę danych. Wszystko będzie czystsze, a gdy nie uda ci się uniknąć znaków, pojawi się błąd składniowy.
Justin Johnson


Można także użyć metod JQuery Escape („ciąg”) i unescape („ciąg”)
Abhiram

Odpowiedzi:


212

Musisz usunąć ciąg, w którym piszesz, DoEditaby wyszorować znaki podwójnego cudzysłowu. Powodują onclickprzedwczesne zamknięcie atrybutu HTML.

Użycie znaku zmiany znaczenia JavaScript \nie jest wystarczające w kontekście HTML. Trzeba wymienić cudzysłów z właściwej reprezentacji XML podmiotu, &quot;.


Racja, ale czy to nie byłoby to? <a href="#" onclick="DoEdit('Preliminary Assessment \"Mini\"'); return false;"> edycja </a> Próbowałem tego i wciąż się psuje. To musi być prosty WTF, ale przez całe życie nie widzę tego.
Matt Dawdy,

Czy jest jakaś wbudowana funkcja JavaScript, która unikałaby podwójnych cudzysłowów? Oprócz „quo”. Replace („”, „& quot;”) nie mogę nic znaleźć.
kevin

4
To nie jest problem z javascript, to problem z kodowaniem HTML / XML: nie możesz zawierać cudzysłowów wewnątrz wartości atrybutów bez ich ucieczki ... w przeciwnym razie przeglądarki / parsery myślą, że kończysz deklarację wartości atrybutu.
Aaron

22
przykładowy kod zastępczy:'mystring'.replace(/"/g, '&quot;');
Joshua Burns

3
w poprzednim komentarzu jest dodatkowy cytat. Działający kod to „mystring” .replace (/ '/ g, „& quot;”);
Agustin Lopez

95

&quot; działałby w tym konkretnym przypadku, jak zasugerowano mi wcześniej, ze względu na kontekst HTML.

Jeśli jednak chcesz, aby kod JavaScript był niezależnie zmieniany niezależnie od kontekstu, możesz wybrać natywne kodowanie JavaScript:
'staje \x27
"się\x22

Twoje kliknięcie stałoby się:
DoEdit('Preliminary Assessment \x22Mini\x22');

Działałoby to na przykład również przy przekazywaniu ciągu JavaScript jako parametru do innej metody JavaScript ( alert()jest to łatwa metoda testowa).

Odsyłam cię do duplikatu pytania o przepełnienie stosu. Jak mogę uniknąć ciągu w kodzie JavaScript w module obsługi onClick? .


2
Dziękuję Ci! Twoja odpowiedź jest bardziej poprawna, ponieważ jest to macierzysty JavaScript bez względu na kontekst.
scarver2

2
To poprawna odpowiedź, chociaż w kontekście HTML użycie &quot;będzie oczywiście działać.
Oliver,

Pamiętaj, że &quot;jest to wymagane w wartościach wejściowych, tzn. <input value="\x22quoted string\x22">Nie będzie działać.
thdoan

@ 10basetom naturalnie, ucieczka JavaScript działa tylko w kontekście JavaScript, podobnie jak programy obsługi zdarzeń ( onclick="..."). Wartość valueatrybutu nie jest przetwarzana w kontekście JavaScript, tylko w kontekście HTML.
tsemer

kod zastępczy:'mystring'.replace(/"/g, '\\x22').replace(/'/g, '\\x27')
kurczaki

33
<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment &quot;Mini&quot;'); return false;">edit</a>
    </body>
</html>

Powinien załatwić sprawę.


24

Ludzie, unescapew JavaScripcie jest już dostępna funkcja, która wykonuje odwzorowanie dla \":

<script type="text/javascript">
    var str="this is \"good\"";
    document.write(unescape(str))
</script>

2
Kombinacja „escape” / „unescape” zrobiła to, czego potrzebowałem. Dzięki.
Luis R.

8
escape / unescape są przestarzałe. chociaż encodeURI robi więcej niż tylko cytaty. gotochriswest.com/blog/2011/05/23/escape-unescape-deprecated
chug2k

12

Problem polega na tym, że HTML nie rozpoznaje znaku zmiany znaczenia. Można obejść ten problem, używając pojedynczych cudzysłowów dla atrybutu HTML i podwójnych cudzysłowów dla kliknięcia.

<a href="#" onclick='DoEdit("Preliminary Assessment \"Mini\""); return false;'>edit</a>

5
Yikes. Zastanawiałem się, dlaczego w przeszłości naturalnie użyłem „atrybutu”. Po prostu nigdy nie zagłębiłem się w to tak głęboko. Dzięki.
Matt Dawdy

6

Zasadniczo tak to robię str.replace(/[\""]/g, '\\"').

var display = document.getElementById('output');
var str = 'class="whatever-foo__input" id="node-key"';
display.innerHTML = str.replace(/[\""]/g, '\\"');

//will return class=\"whatever-foo__input\" id=\"node-key\"
<span id="output"></span>


2

Jeśli składasz HTML w Javie, możesz użyć tej ładnej klasy narzędziowej z Apache commons-lang, aby poprawnie wykonać wszystkie zmiany znaczenia:

org.apache.commons.lang.StringEscapeUtils
Escapes i unescapes Ciągi znaków dla Java, Java Script, HTML, XML i SQL.


Używam org.apache.commons.lang3.StringEscapeUtils.escapeEcmaScript (tekst) do konstruowania metodyExpression w Javie. Dzięki.
Harun

1

Zrobiłem przykładowy przy użyciu jQuery

var descr = 'test"inside"outside';
$(function(){
   $("#div1").append('<a href="#" onclick="DoEdit(descr);">Click Me</a>');       
});

function DoEdit(desc)
{
    alert ( desc );
}

I to działa w Internet Explorer i Firefox.


5
Oczywiście, że tak, ponieważ nie umieszczasz go bezpośrednio w atrybucie. Aby użyć tej metody, musiałbym utworzyć tablicę ciągów JS, a następnie wykonać dowolną liczbę przypisań $ („# divxxx”) ... Mniej niż optymalna, ale dziękuję za sugestię.
Matt Dawdy

1

Możesz skopiować te dwie funkcje (wymienione poniżej) i użyć ich do zmiany / cofnięcia widoku wszystkich cudzysłowów i znaków specjalnych. Nie musisz do tego używać jQuery ani żadnej innej biblioteki.

function escape(s) {
    return ('' + s)
        .replace(/\\/g, '\\\\')
        .replace(/\t/g, '\\t')
        .replace(/\n/g, '\\n')
        .replace(/\u00A0/g, '\\u00A0')
        .replace(/&/g, '\\x26')
        .replace(/'/g, '\\x27')
        .replace(/"/g, '\\x22')
        .replace(/</g, '\\x3C')
        .replace(/>/g, '\\x3E');
}

function unescape(s) {
    s = ('' + s)
       .replace(/\\x3E/g, '>')
       .replace(/\\x3C/g, '<')
       .replace(/\\x22/g, '"')
       .replace(/\\x27/g, "'")
       .replace(/\\x26/g, '&')
       .replace(/\\u00A0/g, '\u00A0')
       .replace(/\\n/g, '\n')
       .replace(/\\t/g, '\t');

    return s.replace(/\\\\/g, '\\');
}

1

Poniżej znajduje się kod, który unika pojedynczych cudzysłowów jako części wprowadzonego ciągu przy użyciu wyrażenia regularnego. Sprawdza, czy ciąg wprowadzony przez użytkownika jest oddzielony przecinkami, a jednocześnie unika nawet pojedynczych cudzysłowów wprowadzonych jako część ciągu.

Aby uniknąć pojedynczych cudzysłowów, po prostu wprowadź ukośnik wstecz, a następnie pojedynczy cudzysłów, taki jak: \ ' jako część ciągu. W tym przykładzie użyłem walidatora jQuery i możesz go używać według swojej wygody.

Prawidłowe ciągi znaków:

'Dzień dobry'

'Witaj świecie'

'Witaj świecie'

'Witaj świecie',' '

„To mój świat”, „Nie mogę się tym cieszyć beze mnie”, „Witamy, Gość”

HTML:

<tr>
    <td>
        <label class="control-label">
            String Field:
        </label>
        <div class="inner-addon right-addon">
            <input type="text" id="stringField"
                   name="stringField"
                   class="form-control"
                   autocomplete="off"
                   data-rule-required="true"
                   data-msg-required="Cannot be blank."
                   data-rule-commaSeparatedText="true"
                   data-msg-commaSeparatedText="Invalid comma separated value(s).">
        </div>
    </td>

JavaScript:

     /**
 *
 * @param {type} param1
 * @param {type} param2
 * @param {type} param3
 */
jQuery.validator.addMethod('commaSeparatedText', function(value, element) {

    if (value.length === 0) {
        return true;
    }
    var expression = new RegExp("^((')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))(((,)|(,\\s))(')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))*$");
    return expression.test(value);
}, 'Invalid comma separated string values.');

0

Unikaj również białych znaków. Wydaje mi się, że Firefox zakłada trzy argumenty zamiast jednego. &nbsp;to nierozerwalna postać spacji. Nawet jeśli to nie jest cały problem, może być dobrym pomysłem.


0

Musisz unikać cudzysłowów z podwójnymi ukośnikami odwrotnymi.

To się nie powiedzie (wyprodukowane przez json_encode PHP ):

<script>
  var jsonString = '[{"key":"my \"value\" "}]';
  var parsedJson = JSON.parse(jsonString);
</script>

To działa:

<script>
  var jsonString = '[{"key":"my \\"value\\" "}]';
  var parsedJson = JSON.parse(jsonString);
</script>

0

Możesz użyć metod jQuery escape () i unescape (). Jak poniżej

Użyj, escape(str);aby uciec z łańcucha i odzyskać ponownie za pomocą unescape(str_esc);.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.