Kann ich HTML-Sonderzeichen in Javascript entkommen?


Antworten:


329
function escapeHtml(unsafe) {
    return unsafe
         .replace(/&/g, "&")
         .replace(/</g, "&lt;")
         .replace(/>/g, "&gt;")
         .replace(/"/g, "&quot;")
         .replace(/'/g, "&#039;");
 }

11
Warum "& # 039;" und nicht "& apos;" ?
Sereda


2
Ich denke, reguläre Ausdrücke in replace()Anrufen sind unnötig. Einfache alte Einzelzeichenfolgen würden genauso gut funktionieren.
Jamix

21
@jamix Sie können keinen globalen Ersatz durch rohe Zeichenfolgen vornehmen, während moderne Browser-Engines den einfachen regulären Ausdruck ziemlich gut optimieren.
bjornd

4
Gibt es eine Standard-API oder ist dies der einzige Weg?
Sunil Garg

55

function escapeHtml(html){
  var text = document.createTextNode(html);
  var p = document.createElement('p');
  p.appendChild(text);
  return p.innerHTML;
}

// Escape while typing & print result
document.querySelector('input').addEventListener('input', e => {
  console.clear();
  console.log( escapeHtml(e.target.value) );
});
<input style='width:90%; padding:6px;' placeholder='&lt;b&gt;cool&lt;/b&gt;'>


Hier arbeiten, aber nicht offline für mich im Browser arbeiten

49

Sie können die .text()Funktion von jQuery verwenden .

Beispielsweise:

http://jsfiddle.net/9H6Ch/

Aus der jQuery-Dokumentation zur .text()Funktion:

Wir müssen uns bewusst sein, dass diese Methode bei Bedarf der angegebenen Zeichenfolge entgeht, damit sie korrekt in HTML gerendert wird. Dazu ruft es die DOM-Methode .createTextNode () auf und interpretiert die Zeichenfolge nicht als HTML.

In früheren Versionen der jQuery-Dokumentation wurde dies folgendermaßen formuliert ( Hervorhebung hinzugefügt ):

Wir müssen uns bewusst sein, dass diese Methode bei Bedarf der angegebenen Zeichenfolge entgeht, damit sie korrekt in HTML gerendert wird. Zu diesem Zweck wird die DOM-Methode .createTextNode () aufgerufen, die Sonderzeichen durch ihre HTML-Entitätsäquivalente ersetzt (z. B. & lt; für <).


3
Sie können es sogar für ein const str = "foo<>'\"&"; $('<div>').text(str).html()foo&lt;&gt;'"&amp;
neues

28

Ich glaube, ich habe den richtigen Weg gefunden ...

// Create a DOM Text node:
var text_node = document.createTextNode(unescaped_text);

// Get the HTML element where you want to insert the text into:
var elem = document.getElementById('msg_span');

// Optional: clear its old contents
//elem.innerHTML = '';

// Append the text node into it:
elem.appendChild(text_node);

Ich habe heute etwas Neues über HTML gelernt. w3schools.com/jsref/met_document_createtextnode.asp .
Sellorio

1
document.createTextNode("<script>alert('Attack!')</script>").textContent
Beachten

Dies ist der richtige Weg, wenn Sie nur Text einstellen. Das ist auch textContent, aber anscheinend wird es nicht gut unterstützt. Dies funktioniert jedoch nicht, wenn Sie eine Zeichenfolge mit einigen Teilen Text und HTML erstellen, müssen Sie trotzdem entkommen.
jgmjgm


20

Dies ist bei weitem der schnellste Weg, den ich je gesehen habe. Außerdem wird alles erledigt, ohne Elemente auf der Seite hinzuzufügen, zu entfernen oder zu ändern.

function escapeHTML(unsafeText) {
    let div = document.createElement('div');
    div.innerText = unsafeText;
    return div.innerHTML;
}

7
Warnung: Es werden keine Anführungszeichen ausgegeben, sodass Sie die Ausgabe nicht in Attributwerten im HTML-Code verwenden können. ZB var divCode = '<div data-title="' + escapeHTML('Jerry "Bull" Winston') + '">Div content</div>'ergibt ungültiges HTML!
izogfif

16

Es war interessant, eine bessere Lösung zu finden:

var escapeHTML = function(unsafe) {
  return unsafe.replace(/[&<"']/g, function(m) {
    switch (m) {
      case '&':
        return '&amp;';
      case '<':
        return '&lt;';
      case '"':
        return '&quot;';
      default:
        return '&#039;';
    }
  });
};

Ich analysiere nicht, >weil es XML / HTML-Code im Ergebnis nicht bricht.

Hier sind die Benchmarks: http://jsperf.com/regexpairs Außerdem habe ich eine universelle escapeFunktion erstellt: http://jsperf.com/regexpairs2


1
Es ist interessant zu sehen, dass die Verwendung des Schalters erheblich schneller ist als die Karte. Das habe ich nicht erwartet! Danke für das Teilen!
Peter T.

Es gibt viel, viel mehr Unicode-Zeichen, als Sie codieren und berücksichtigen könnten. Ich würde diese manuelle Methode überhaupt nicht empfehlen.
vsync

Warum würden Sie Multibyte-Zeichen überhaupt entkommen? Verwenden Sie UTF-8 einfach überall.
Neonit

3
Überspringen> kann möglicherweise den Code beschädigen. Sie müssen bedenken, dass im <> auch HTML enthalten ist. In diesem Fall wird das Überspringen> unterbrochen. Wenn Sie nur zwischen Tags fliehen, benötigen Sie wahrscheinlich nur Escape <und &.
jgmjgm

8

Die prägnanteste und performanteste Möglichkeit, nicht codierten Text anzuzeigen, ist die Verwendung von textContentEigenschaften.

Schneller als mit innerHTML. Und das ohne Berücksichtigung des Overheads.

document.body.textContent = 'a <b> c </b>';


@ZzZombo, es ist völlig normal, dass es nicht mit Stil- und Skript-Tags funktioniert. Wenn Sie ihnen Inhalte hinzufügen, fügen Sie Code hinzu , nicht Text . Verwenden Sie in diesem Fall innerHTML. Darüber hinaus müssen Sie nicht entkommen, dies sind zwei spezielle Tags, die nicht als HTML analysiert werden. Beim Parsen wird ihr Inhalt als Text behandelt, bis die Abschlusssequenz erreicht </ist.
Benutzer

6

DOM-Elemente unterstützen die Konvertierung von Text in HTML durch Zuweisung zu innerText . innerText ist keine Funktion, aber die Zuweisung funktioniert so, als ob der Text maskiert wäre.

document.querySelectorAll('#id')[0].innerText = 'unsafe " String >><>';

1
Zumindest in Chrome werden durch das Zuweisen von mehrzeiligem Text <br>Elemente anstelle von Zeilenumbrüchen hinzugefügt, die bestimmte Elemente wie Stile oder Skripte beschädigen können. Das createTextNodeist nicht anfällig für dieses Problem.
ZzZombo

1
innerTexthat einige Legacy- / Spezifikationsprobleme. Besser zu benutzen textContent.
Roy Tinker

3

Sie können jedes Zeichen in Ihrer Zeichenfolge codieren:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

Oder zielen Sie einfach auf die Hauptfiguren, über die Sie sich Sorgen machen möchten (&, Inebreaks, <,>, "und '), wie:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('How to encode\nonly html tags &<>\'" nice & fast!');

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55">&#119;&#119;&#119;&#46;&#87;&#72;&#65;&#75;&#46;&#99;&#111;&#109;</textarea>


Das Schreiben einer eigenen Escape-Funktion ist im Allgemeinen eine schlechte Idee. Andere Antworten sind in dieser Hinsicht besser.
Jannis

2

Ein Einzeiler (für ES6 +):

var escapeHtml = s => (s + '').replace(/[&<>"']/g, m => ({
    '&': '&amp;', '<': '&lt;', '>': '&gt;',
    '"': '&quot;', "'": '&#39;'
})[m]);

Für ältere Versionen:

function escapeHtml(s) {
    return (s + '').replace(/[&<>"']/g, function (m) {
        return ({
            '&': '&amp;', '<': '&lt;', '>': '&gt;',
            '"': '&quot;', "'": '&#39;'
        })[m];
    });
}

0

Ist beim Erstellen einer DOM-Struktur auf dieses Problem gestoßen. Diese Frage hat mir geholfen, sie zu lösen. Ich wollte einen Doppel-Chevron als Pfadtrennzeichen verwenden, aber das Anhängen eines neuen Textknotens führte direkt dazu, dass der maskierte Zeichencode angezeigt wurde und nicht das Zeichen selbst:

var _div = document.createElement('div');
var _separator = document.createTextNode('&raquo;');
//_div.appendChild(_separator); /* this resulted in '&raquo;' being displayed */
_div.innerHTML = _separator.textContent; /* this was key */

0

Wenn Sie bereits Module in Ihrer App verwenden, können Sie das Escape-HTML- Modul verwenden.

import escapeHtml from 'escape-html';
const unsafeString = '<script>alert("XSS");</script>';
const safeString = escapeHtml(unsafeString);


-4

Ich habe diese Lösung gefunden.

Nehmen wir an, wir möchten dem Element HTML mit unsicheren Daten des Benutzers oder der Datenbank hinzufügen.

var unsafe = 'some unsafe data like <script>alert("oops");</script> here';

var html = '';
html += '<div>';
html += '<p>' + unsafe + '</p>';
html += '</div>';

element.html(html);

Es ist unsicher gegen XSS-Angriffe. Fügen Sie dies nun hinzu.

$(document.createElement('div')).html(unsafe).text();

So ist es

var unsafe = 'some unsafe data like <script>alert("oops");</script> here';

var html = '';
html += '<div>';
html += '<p>' + $(document.createElement('div')).html(unsafe).text(); + '</p>';
html += '</div>';

element.html(html);

Für mich ist das viel einfacher als zu benutzen .replace()und es wird entfernt !!! alle möglichen HTML-Tags (hoffe ich).


Dies ist eine gefährliche Idee. Sie analysiert den unsicheren HTML-String als HTML. Wenn das Element an das DOM angehängt würde, würde es ausgeführt. Verwenden Sie stattdessen .innerText.
Teknopaul

Das ist nicht sicher. Es wandelt sich &lt;script&gt;in <script>.
FGB
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.