773 Stimmen

HTML-Kodierung geht verloren, wenn Attribut aus Eingabefeld gelesen wird

Ich verwende JavaScript, um einen Wert aus einem verborgenen Feld zu ziehen und ihn in einem Textfeld anzuzeigen. Der Wert im verborgenen Feld ist kodiert.

Zum Beispiel,

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />

wird hineingezogen

<input type='text' value='chalk &amp; cheese' />

über einige jQuery, um den Wert aus dem ausgeblendeten Feld zu erhalten (es ist an diesem Punkt, dass ich die Codierung verlieren):

$('#hiddenId').attr('value')

Das Problem ist, dass ich beim Lesen chalk &amp; cheese aus dem verborgenen Feld, scheint JavaScript die Kodierung zu verlieren. Ich möchte nicht, dass der Wert zu sein chalk & cheese . Ich möchte die wörtliche amp; beibehalten werden.

Gibt es eine JavaScript-Bibliothek oder eine jQuery-Methode, die eine Zeichenkette in HTML kodiert?

0 Stimmen

Können Sie das von Ihnen verwendete Javascript zeigen?

1 Stimmen

Ich habe hinzugefügt, wie ich einen Wert aus einem versteckten Feld erhalte

0 Stimmen

1074voto

Christian C. Salvadó Punkte 763569

EDIT: Diese Antwort wurde vor langer Zeit veröffentlicht, und die htmlDecode Funktion wurde eine XSS-Schwachstelle eingeführt. Sie wurde geändert, indem das temporäre Element von einem div zu einer textarea Verringerung des XSS-Risikos. Heutzutage würde ich Ihnen jedoch empfehlen, die DOMParser-API zu verwenden, wie sie in andere Anwaltskanzlei .


Ich verwende diese Funktionen:

function htmlEncode(value){
  // Create a in-memory element, set its inner text (which is automatically encoded)
  // Then grab the encoded contents back out. The element never exists on the DOM.
  return $('<textarea/>').text(value).html();
}

function htmlDecode(value){
  return $('<textarea/>').html(value).text();
}

Grundsätzlich wird ein Textarea-Element im Speicher erstellt, aber nie an das Dokument angehängt.

Auf der htmlEncode Funktion setze ich die innerText des Elements, und rufen Sie die verschlüsselte innerHTML auf der htmlDecode Funktion setze ich die innerHTML Wert des Elements und der innerText abgerufen wird.

Prüfen Sie ein laufendes Beispiel aquí .

565voto

Anentropic Punkte 28341

Der jQuery-Trick kodiert keine Anführungszeichen, und im IE werden die Leerzeichen entfernt.

Auf der Grundlage der Flucht templatetag in Django, die ich vermute, ist stark genutzt/getestet bereits, ich machte diese Funktion, die tut, was benötigt wird.

Es ist wohl einfacher (und möglicherweise schneller) als alle Workarounds für das Whitespace-Stripping-Problem - und es kodiert Anführungszeichen, was unerlässlich ist, wenn Sie das Ergebnis beispielsweise innerhalb eines Attributwerts verwenden möchten.

function htmlEscape(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
}

// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
    return str
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

Update 2013-06-17:
Auf der Suche nach dem schnellsten Escaping habe ich diese Implementierung eines replaceAll método:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(Auch hier wird darauf verwiesen: Schnellste Methode zum Ersetzen aller Instanzen eines Zeichens in einer Zeichenkette )
Hier einige Leistungsergebnisse:
http://jsperf.com/htmlencoderegex/25

Sie liefert die gleiche Ergebniszeichenkette wie die eingebaute replace Ketten oben. Ich würde mich sehr freuen, wenn mir jemand erklären könnte, warum das schneller geht!?

Update 2015-03-04:
Mir ist gerade aufgefallen, dass AngularJS genau die obige Methode verwendet:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

Sie fügen eine Reihe von Verfeinerungen hinzu - sie scheinen mit einem obskures Unicode-Problem sowie die Umwandlung aller nicht alphanumerischen Zeichen in Entitäten. Ich hatte den Eindruck, dass letzteres nicht notwendig ist, solange Sie einen UTF8-Zeichensatz für Ihr Dokument festgelegt haben.

Ich möchte anmerken, dass (4 Jahre später) Django immer noch keines dieser Dinge tut, also bin ich nicht sicher, wie wichtig sie sind:
https://github.com/django/django/blob/1.8b1/django/utils/html.py#L44

Update 2016-04-06:
Möglicherweise möchten Sie auch den Schrägstrich / . Dies ist für eine korrekte HTML-Kodierung nicht erforderlich, aber es ist empfohlen von OWASP als Sicherheitsmaßnahme gegen XSS. (Dank an @JNF für diesen Vorschlag in den Kommentaren)

        .replace(/\//g, '&#x2F;');

83voto

ThinkingStiff Punkte 63624

Hier ist eine Version ohne jQuery, die wesentlich schneller ist als die jQuery .html() Version und die .replace() Version. Dabei bleiben alle Leerzeichen erhalten, aber wie bei der jQuery-Version werden Anführungszeichen nicht berücksichtigt.

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

Geschwindigkeit: http://jsperf.com/htmlencoderegex/17

speed test

Demo: <a href="http://jsfiddle.net/ThinkingStiff/FSaU2/"><img src="https://i.stack.imgur.com/NI3c4.png" alt="jsFiddle"></a>

Ausgabe:

output

Drehbuch:

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

function htmlDecode( html ) {
    var a = document.createElement( 'a' ); a.innerHTML = html;
    return a.textContent;
};

document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );

//sanity check
var html = '<div>   &amp; hello</div>';
document.getElementById( 'same' ).textContent = 
      'html === htmlDecode( htmlEncode( html ) ): ' 
    + ( html === htmlDecode( htmlEncode( html ) ) );

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>

32voto

boca Punkte 2272

Ich weiß, dass dies ein alter Beitrag ist, aber ich wollte eine Variation von die akzeptierte Antwort die im IE funktionieren, ohne Zeilen zu entfernen:

function multiLineHtmlEncode(value) {
    var lines = value.split(/\r\n|\r|\n/);
    for (var i = 0; i < lines.length; i++) {
        lines[i] = htmlEncode(lines[i]);
    }
    return lines.join('\r\n');
}

function htmlEncode(value) {
    return $('<div/>').text(value).html();
}

29voto

TJ VanToll Punkte 12296

Unterstrich bietet _.escape() y _.unescape() Methoden, die dies tun.

> _.unescape( "chalk &amp; cheese" );
  "chalk & cheese"

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X