Posso evitare caratteri speciali html in javascript?


Risposte:


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

11
Perché "& # 039;" e non "& apos;" ?
Sereda,


2
Penso che le espressioni regolari nelle replace()chiamate non siano necessarie. Anche le semplici stringhe a singolo carattere andrebbero bene.
Jamix,

22
@jamix Non puoi fare una sostituzione globale con stringhe non elaborate, mentre i moderni motori di browser ottimizzano abbastanza bene l'espressione regolare semplice.
bjornd,

5
c'è qualche API standard o questo è l'unico modo?
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;'>


Lavoro qui ma non lavoro offline per me nel browser

48

Puoi usare la .text()funzione di jQuery .

Per esempio:

http://jsfiddle.net/9H6Ch/

Dalla documentazione di jQuery relativa alla .text()funzione:

Dobbiamo essere consapevoli che questo metodo sfugge alla stringa fornita come necessario in modo che venga visualizzato correttamente in HTML. Per fare ciò, chiama il metodo DOM .createTextNode (), non interpreta la stringa come HTML.

Le versioni precedenti della documentazione jQuery erano formulate in questo modo ( enfasi aggiunta ):

Dobbiamo essere consapevoli che questo metodo sfugge alla stringa fornita come necessario in modo che venga visualizzato correttamente in HTML. Per fare ciò, chiama il metodo DOM .createTextNode (), che sostituisce i caratteri speciali con i loro equivalenti di entità HTML (come & lt; per <).


3
Puoi persino usarlo su un nuovo elemento se vuoi solo convertirti in questo modo: const str = "foo<>'\"&"; $('<div>').text(str).html()yieldsfoo&lt;&gt;'"&amp;
amoebe

28

Penso di aver trovato il modo giusto di farlo ...

// 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);

Oggi ho imparato qualcosa di nuovo sull'HTML. w3schools.com/jsref/met_document_createtextnode.asp .
Sellorio,

1
Tenere presente che il contenuto del nodo di testo non viene document.createTextNode("<script>alert('Attack!')</script>").textContent
eliminato

Questo è il modo corretto se tutto ciò che stai facendo è impostare il testo. Anche questo è TextContent ma a quanto pare non è ben supportato. Questo non funzionerà comunque se stai costruendo una stringa con alcune parti di testo in html, allora devi ancora scappare.
jgmjgm,


21

Questo è di gran lunga il modo più veloce in cui l'ho visto fare. Inoltre, fa tutto senza aggiungere, rimuovere o modificare elementi nella pagina.

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

7
Attenzione: non sfugge alle virgolette, quindi non è possibile utilizzare l'output all'interno dei valori degli attributi nel codice HTML. Ad esempio var divCode = '<div data-title="' + escapeHTML('Jerry "Bull" Winston') + '">Div content</div>'produrrà HTML non valido!
izogfif,

17

È stato interessante trovare una soluzione migliore:

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

Non analizzo >perché non interrompe il codice XML / HTML nel risultato.

Ecco i parametri di riferimento: http://jsperf.com/regexpairs Inoltre, ho creato una escapefunzione universale : http://jsperf.com/regexpairs2


1
È interessante notare che l'utilizzo dell'interruttore è significativamente più veloce della mappa. Non me l'aspettavo! Grazie per la condivisione!
Peter T.

Esistono molti più caratteri unicode di quanti potresti codificare e prendere in considerazione. Non consiglierei affatto questo metodo manuale.
vsync,

Perché dovresti sfuggire ai caratteri multibyte? Usa UTF-8 ovunque.
Neonit,

4
Saltare> può potenzialmente rompere il codice. Devi tenere presente che all'interno di <> è presente anche html. In tal caso, il salto> verrà interrotto. Se stai scappando solo tra i tag, probabilmente hai bisogno solo di escape <e &.
jgmjgm,

8

Il modo più conciso e performante per visualizzare testo non codificato è usare la textContentproprietà.

Più veloce dell'uso innerHTML. E questo senza tener conto dell'evasione delle spese generali.

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


@ZzZombo, è del tutto normale che non funzioni con tag di stile e script. Quando aggiungi del contenuto, aggiungi codice , non testo , in questo caso usi innerHTML. Inoltre, non è necessario evitarlo, si tratta di due tag speciali che non vengono analizzati come HTML. Durante l'analisi, il loro contenuto viene trattato come testo fino a quando non </viene rispettata la sequenza di chiusura .
utente

6

DOM Elements supporta la conversione di testo in HTML assegnando a innerText . innerText non è una funzione ma l'assegnazione ad essa funziona come se il testo fosse evaso.

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

1
Almeno in Chrome l'assegnazione di testo multilinea aggiunge <br>elementi al posto di nuove righe, che possono interrompere determinati elementi, come stili o script. Non createTextNodeè soggetto a questo problema.
ZzZombo,

1
innerTextpresenta alcuni problemi di eredità / specifiche. Meglio usare textContent.
Roy Tinker,

3

Puoi codificare tutti i caratteri nella tua stringa:

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

Oppure scegli come target i personaggi principali di cui preoccuparti (&, inebreaks, <,>, "e ') come:

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>


Scrivere la tua funzione di escape è generalmente una cattiva idea. Altre risposte sono migliori in questo senso.
jannis,

2

Un one-liner (per ES6 +):

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

Per le versioni precedenti:

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

0

Ho riscontrato questo problema durante la creazione di una struttura DOM. Questa domanda mi ha aiutato a risolverlo. Volevo usare un doppio chevron come separatore di percorso, ma l'aggiunta di un nuovo nodo di testo ha portato direttamente alla visualizzazione del codice carattere sfuggito, piuttosto che al carattere stesso:

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

Se usi già moduli nella tua app, puoi usare il modulo escape-html .

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

-3

Prova questo, usando la prototype.jslibreria:

string.escapeHTML();

Prova una demo


5
Ciò richiede la libreria "prototype.js", che non era immediatamente evidente dalla demo. :(
audiodude

-4

Ho trovato questa soluzione.

Supponiamo di voler aggiungere dell'html all'elemento con dati non sicuri dell'utente o del database.

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

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

element.html(html);

Non è sicuro contro gli attacchi XSS. Ora aggiungi questo.

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

Così è

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);

Per me questo è molto più semplice dell'uso .replace()e lo rimuoverà !!! tutti i possibili tag html (spero).


questa è un'idea pericolosa, analizza la stringa HTML non sicura come HTML, se l'elemento fosse collegato al DOM verrebbe eseguito. usa invece .innerText.
Teknopaul,

Questo non è sicuro Si converte &lt;script&gt;in <script>.
fgb,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.