Domanda

Qualcuno conosce un modo semplice per sfuggire all'HTML dalle stringhe in jQuery?Devo essere in grado di passare una stringa arbitraria e di averla correttamente sottoposta a escape per la visualizzazione in una pagina HTML (prevenendo attacchi di iniezione JavaScript/HTML).Sono sicuro che sia possibile estendere jQuery per fare ciò, ma al momento non ne so abbastanza del framework per raggiungere questo obiettivo.

È stato utile?

Soluzione

Dal momento che stai usando jQuery, puoi semplicemente impostare l'elemento text proprietà:

// before:
// <div class="someClass">text</div>
var someHtmlString = "<script>alert('hi!');</script>";

// set a DIV's text:
$("div.someClass").text(someHtmlString);
// after: 
// <div class="someClass">&lt;script&gt;alert('hi!');&lt;/script&gt;</div>

// get the text in a string:
var escaped = $("<div>").text(someHtmlString).html();
// value: 
// &lt;script&gt;alert('hi!');&lt;/script&gt;

Altri suggerimenti

C'è anche la soluzione da mustache.js

var entityMap = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#39;',
  '/': '&#x2F;',
  '`': '&#x60;',
  '=': '&#x3D;'
};

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}
$('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff"

Fonte: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb

Se stai scappando per HTML, ce ne sono solo tre che posso pensare che sarebbero davvero necessari:

html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

A seconda del caso d'uso, potresti anche dover fare cose come " A &quot;.Se l'elenco diventasse abbastanza grande, userei semplicemente un array:

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]
for(var item in findReplace)
    escaped = escaped.replace(findReplace[item][0], findReplace[item][1]);

encodeURIComponent() lo effettuerà l'escape solo per gli URL, non per l'HTML.

Ho scritto una piccola funzione che fa questo.Sfugge soltanto ", &, < E > (ma di solito è tutto ciò che serve comunque).È leggermente più elegante delle soluzioni proposte in precedenza in quanto utilizza solo uno .replace() per fare tutta la conversione.(MODIFICA 2: Ridotta complessità del codice rendendo la funzione ancora più piccola e ordinata, se sei curioso del codice originale vedi la fine di questa risposta.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&<>]/g, function (a) {
        return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
    });
}

Questo è semplice Javascript, non viene utilizzato jQuery.

In fuga / E ' pure

Modifica in risposta a mklementil commento di.

La funzione di cui sopra può essere facilmente espansa per includere qualsiasi carattere.Per specificare più caratteri di cui eseguire l'escape, è sufficiente inserirli entrambi nella classe dei caratteri nell'espressione regolare (ad es.dentro il /[...]/g) e come voce nel chr oggetto.(MODIFICA 2: Accorciata anche questa funzione, allo stesso modo.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&'\/<>]/g, function (a) {
        return {
            '"': '&quot;', '&': '&amp;', "'": '&#39;',
            '/': '&#47;',  '<': '&lt;',  '>': '&gt;'
        }[a];
    });
}

Notare l'uso di cui sopra &#39; per apostrofo (l'entità simbolica &apos; potrebbe essere stato utilizzato al suo posto: è definito in XML, ma originariamente non era incluso nelle specifiche HTML e pertanto potrebbe non essere supportato da tutti i browser.Vedere: Articolo di Wikipedia sulle codifiche dei caratteri HTML).Ricordo anche di aver letto da qualche parte che l'uso di entità decimali è più ampiamente supportato rispetto all'uso esadecimale, ma ora non riesco a trovarne la fonte.(E non possono esserci molti browser sul mercato che non supportano le entità esadecimali.)

Nota: Aggiunta / E ' all'elenco dei caratteri di escape non è poi così utile, poiché non hanno alcun significato speciale in HTML e non lo hanno Bisogno essere fuggito.

Originale escapeHtml Funzione

MODIFICA 2: La funzione originale utilizzava una variabile (chr) per memorizzare l'oggetto necessario per il .replace() richiamare.Questa variabile necessitava anche di una funzione anonima extra per definirne l'ambito, rendendo la funzione (inutilmente) un po' più grande e complessa.

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());

Non ho testato quale delle due versioni sia più veloce.Se lo fai, sentiti libero di aggiungere informazioni e link a riguardo qui.

Abbastanza facile da usare

_.escape(string) 

Sottolineare è una libreria di utilità che fornisce molte funzionalità che il nativo js non fornisce.C'è anche lodash che è la stessa API del carattere di sottolineatura ma è stata riscritta per essere più performante.

Mi rendo conto di quanto sono in ritardo per questa festa, ma ho una soluzione molto semplice che non richiede jQuery.

escaped = new Option(unescaped).innerHTML;

Modificare:Questo non sfugge alle virgolette.L'unico caso in cui è necessario eseguire l'escape delle virgolette è se il contenuto verrà incollato in linea su un attributo all'interno di una stringa HTML.È difficile per me immaginare un caso in cui fare questo sarebbe un buon design.

Modifica 2:Se le prestazioni sono cruciali, la soluzione con le prestazioni più elevate (di circa il 50%) è ancora una serie di sostituzioni regex.I browser moderni rileveranno che le espressioni regolari non contengono operatori, solo una stringa, e le comprimeranno tutte in un'unica operazione.

Ecco una funzione JavaScript pulita e chiara.Il testo come "pochi < molti" verrà trasformato in "pochi <molti".

function escapeHtmlEntities (str) {
  if (typeof jQuery !== 'undefined') {
    // Create an empty div to use as a container,
    // then put the raw text in and get the HTML
    // equivalent out.
    return jQuery('<div/>').text(str).html();
  }

  // No jQuery, so use string replace.
  return str
    .replace(/&/g, '&amp;')
    .replace(/>/g, '&gt;')
    .replace(/</g, '&lt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&apos;');
}

Dopo gli ultimi test posso consigliarlo più veloce e completamente browser incrociati compatibile JavaScript nativo (DOM) soluzione:

function HTMLescape(html){
    return document.createElement('div')
        .appendChild(document.createTextNode(html))
        .parentNode
        .innerHTML
}

Se lo ripeti più volte puoi farlo con le variabili una volta preparate:

//prepare variables
var DOMtext = document.createTextNode("test");
var DOMnative = document.createElement("span");
DOMnative.appendChild(DOMtext);

//main work for each case
function HTMLescape(html){
  DOMtext.nodeValue = html;
  return DOMnative.innerHTML
}

Guarda la mia performance finale confronto (domanda sullo stack).

Tentativo Sottolineato.string lib, funziona con jQuery.

_.str.escapeHTML('<div>Blah blah blah</div>')

produzione:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'

Ho migliorato l'esempio mustache.js aggiungendo il file escapeHTML() metodo all'oggetto stringa.

var __entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
};

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function (s) {
        return __entityMap[s];
    });
}

In questo modo è abbastanza facile da usare "Some <text>, more Text&Text".escapeHTML()

escape() E unescape() hanno lo scopo di codificare/decodificare stringhe per URL, non HTML.

In realtà, utilizzo il seguente snippet per eseguire il trucco che non richiede alcun framework:

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');

Se hai underscore.js, usa _.escape (più efficiente del metodo jQuery pubblicato sopra):

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe

Se stai seguendo il percorso regex, c'è un errore nell'esempio di tghw sopra.

<!-- WON'T WORK -  item[0] is an index, not an item -->

var escaped = html; 
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g,"&gt;"], [/"/g,
"&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(item[0], item[1]);   
}


<!-- WORKS - findReplace[item[]] correctly references contents -->

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]);
}

Questo è un bell'esempio sicuro...

function escapeHtml(str) {
    if (typeof(str) == "string"){
        try{
            var newStr = "";
            var nextCode = 0;
            for (var i = 0;i < str.length;i++){
                nextCode = str.charCodeAt(i);
                if (nextCode > 0 && nextCode < 128){
                    newStr += "&#"+nextCode+";";
                }
                else{
                    newStr += "?";
                }
             }
             return newStr;
        }
        catch(err){
        }
    }
    else{
        return str;
    }
}

Puoi farlo facilmente con Vanilla js.

Aggiungi semplicemente un nodo di testo al documento.Verrà sfuggito dal browser.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)
(function(undefined){
    var charsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };

    var replaceReg = new RegExp("[" + Object.keys(charsToReplace).join("") + "]", "g");
    var replaceFn = function(tag){ return charsToReplace[tag] || tag; };

    var replaceRegF = function(replaceMap) {
        return (new RegExp("[" + Object.keys(charsToReplace).concat(Object.keys(replaceMap)).join("") + "]", "gi"));
    };
    var replaceFnF = function(replaceMap) {
        return function(tag){ return replaceMap[tag] || charsToReplace[tag] || tag; };
    };

    String.prototype.htmlEscape = function(replaceMap) {
        if (replaceMap === undefined) return this.replace(replaceReg, replaceFn);
        return this.replace(replaceRegF(replaceMap), replaceFnF(replaceMap));
    };
})();

Nessuna variabile globale, qualche ottimizzazione della memoria.Utilizzo:

"some<tag>and&symbol©".htmlEscape({'©': '&copy;'})

il risultato è:

"some&lt;tag&gt;and&amp;symbol&copy;"
function htmlEscape(str) {
    var stringval="";
    $.each(str, function (i, element) {
        alert(element);
        stringval += element
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(' ', '-')
            .replace('?', '-')
            .replace(':', '-')
            .replace('|', '-')
            .replace('.', '-');
    });
    alert(stringval);
    return String(stringval);
}

2 metodi semplici che non richiedono JQUERY...

Puoi codificare tutti i caratteri nella tua stringa in questo modo:

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

O semplicemente prendere di mira i personaggi principali preoccuparsi di &, interruzioni di riga, <, >, " E ' Piace:

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

var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';

test.value=encode(myString);

testing.innerHTML=encode(myString);

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<p><b>What JavaScript Generated:</b></p>

<textarea id=test rows="3" cols="55"></textarea>

<p><b>What It Renders Too In HTML:</b></p>

<div id="testing">www.WHAK.com</div>

Semplice esempio di escape JavaScript:

function escapeHtml(text) {
    var div = document.createElement('div');
    div.innerText = text;
    return div.innerHTML;
}

escapeHtml("<script>alert('hi!');</script>")
// "&lt;script&gt;alert('hi!');&lt;/script&gt;"
function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

funziona come un incantesimo

Questa risposta fornisce i metodi jQuery e JS normali, ma questo è il più breve senza utilizzare il DOM:

unescape(escape("It's > 20% less complicated this way."))

Stringa di escape: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

Se gli spazi di escape ti danno fastidio, prova:

unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

Stringa di escape: It%27s %3E 20%25 less complicated this way.

Sfortunatamente, il escape() la funzione era deprecato nella versione JavaScript 1.5. encodeURI() O encodeURIComponent() sono alternative, ma le ignorano ', quindi l'ultima riga di codice si trasformerebbe in questa:

decodeURI(encodeURI("It's > 20% less complicated this way.").replace(/%20/g, " ").replace("'", '%27'))

Tutti i principali browser supportano ancora il codice breve e, dato il numero di vecchi siti Web, dubito che cambierà presto.

Se stai salvando queste informazioni in un file Banca dati, è sbagliato eseguire l'escape dell'HTML utilizzando a dalla parte del cliente script, questo dovrebbe essere fatto nel file server.Altrimenti è facile bypassare la protezione XSS.

Per chiarire il mio punto, ecco un esempio che utilizza una delle risposte:

Supponiamo che tu stia utilizzando la funzione escapeHtml per sfuggire all'Html da un commento nel tuo blog e quindi pubblicarlo sul tuo server.

var entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

L'utente potrebbe:

  • Modifica i parametri della richiesta POST e sostituisci il commento con il codice javascript.
  • Sovrascrivi la funzione escapeHtml utilizzando la console del browser.

Se l'utente incolla questo snippet nella console, ignorerebbe la convalida XSS:

function escapeHtml(string){
   return string
}

Tutte le soluzioni sono inutili se non si impedisce la fuga, ad es.la maggior parte delle soluzioni continuerebbero a sfuggire & A &amp;.

escapeHtml = function (s) {
    return s ? s.replace(
        /[&<>'"]/g,
        function (c, offset, str) {
            if (c === "&") {
                var substr = str.substring(offset, offset + 6);
                if (/&(amp|lt|gt|apos|quot);/.test(substr)) {
                    // already escaped, do not re-escape
                    return c;
                }
            }
            return "&" + {
                "&": "amp",
                "<": "lt",
                ">": "gt",
                "'": "apos",
                '"': "quot"
            }[c] + ";";
        }
    ) : "";
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top