Rømmer HTML strenger med jQuery

stemmer
549

Er det noen som vet om en enkel måte å flykte HTML fra strenger i jQuery ? Jeg må være i stand til å passere en vilkårlig streng og ha det skikkelig rømt for visning i en HTML-side (hindrer Javascript / HTML-injeksjon angrep). Jeg er sikker på at det er mulig å utvide jQuery å gjøre dette, men jeg vet ikke nok om rammene i øyeblikket for å oppnå dette.

Publisert på 24/08/2008 klokken 02:52
kilden bruker
På andre språk...                            


24 svar

stemmer
533

Det er også løsningen fra mustache.js

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

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}
Svarte 20/08/2012 kl. 08:21
kilden bruker

stemmer
394

Siden du bruker jQuery , kan du bare sette elementets texteiendom:

// 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;
Svarte 24/08/2008 kl. 17:22
kilden bruker

stemmer
177
$('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff"

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

Svarte 17/12/2008 kl. 10:28
kilden bruker

stemmer
58

Hvis du rømmer for HTML, er det bare tre som jeg kan tenke på som ville være veldig nødvendig:

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

Avhengig av brukstilfelle, må du kanskje også å gjøre ting som "å &quot;. Hvis listen fikk stor nok, vil jeg bare bruke en matrise:

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() vil bare slippe det for webadresser, ikke for HTML.

Svarte 24/08/2008 kl. 05:54
kilden bruker

stemmer
35

Jeg skrev en bitte liten funksjon som gjør dette. Det rømming bare ", &, <og >(men vanligvis det er alt du trenger uansett). Det er litt mer elegant da de tidligere foreslåtte løsninger i at den bare bruker en .replace() til å gjøre alt konverteringen. ( EDIT 2: Redusert kode kompleksitet gjør funksjonen enda mindre og penere, hvis du er nysgjerrig på den opprinnelige koden se slutten av dette svaret.)

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

Dette er vanlig Javascript, brukte ingen jQuery.

Rømmer /og 'også

Rediger svar på mklement 's kommentar.

Den ovennevnte funksjon kan enkelt utvides til å omfatte hvilket som helst tegn. Hvis du vil angi flere tegn til å unnslippe, bare setter dem begge i tegnklassen i det vanlige uttrykket (dvs. inni /[...]/g) og som en oppføring i chrobjektet. ( EDIT 2: Kortere denne funksjonen også, på samme måte.)

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

Legg merke til over bruk av &#39;for apostrof (symbolsk enhet &apos;kan ha blitt brukt i stedet - det er definert i XML, men var opprinnelig ikke inkludert i HTML spec og kan derfor ikke støttes av alle nettlesere Se:. Wikipedia artikkel om HTML tegnkodinger ). Jeg husker også leste et sted at bruk av desimaltall enheter er mer utbredt støtte enn å bruke heksadesimale, men jeg kan ikke synes å finne kilden for at nå skjønt. (Og det kan ikke være mange nettlesere der ute som ikke støtter de heksadesimale enheter.)

Merk: Legge /og 'til listen over rømt tegn er ikke alle som nyttig, siden de ikke har noen spesiell betydning i HTML, og ikke trenger å være rømt.

opprinnelige escapeHtmlfunksjon

EDIT 2: Den opprinnelige funksjon benyttes en variabel ( chr) for å lagre den gjenstand som trengs for .replace()tilbakeringing. Denne variabelen også trengte en ekstra anonym funksjon til omfang det, gjør funksjonen (unødvendig) en litt større og mer komplekse.

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

Jeg har ikke testet hvilken av de to versjonene er raskere. Hvis du gjør det, må du gjerne legge til informasjon og linker om det her.

Svarte 14/11/2012 kl. 00:39
kilden bruker

stemmer
31

Lett nok til å bruke understrek:

_.escape(string) 

Strek er et verktøy bibliotek som gir en rekke funksjoner som innfødte js ikke gir. Det er også lodash som er det samme API som understrek, men ble omskrevet til å være mer performant.

Svarte 12/09/2013 kl. 05:30
kilden bruker

stemmer
29

Jeg innser hvor sent jeg er til dette partiet, men jeg har en veldig enkel løsning som ikke krever jQuery.

escaped = new Option(unescaped).innerHTML;

Edit: Dette betyr ikke unnslippe anførselstegn. Det eneste tilfellet hvor sitater må være rømt er hvis innholdet kommer til å bli limt inline til et attributt i en HTML streng. Det er vanskelig for meg å forestille seg en sak der å gjøre dette ville være bra design.

Edit 2: Hvis ytelsen er avgjørende, er den høyeste ytelse løsning (med ca 50%) fortsatt en rekke regex erstatter. Moderne nettlesere vil oppdage at de regulære uttrykk inneholder ingen operatører, bare en streng, og skjule alle av dem i en enkelt operasjon.

Svarte 01/03/2016 kl. 22:55
kilden bruker

stemmer
26

Her er en ren, klar Javascript-funksjonen. Det vil unnslippe tekst som "noen <mange" til "noen & lt; mange".

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;');
}
Svarte 30/05/2012 kl. 23:46
kilden bruker

stemmer
24

Prøv Underscore.string lib, det fungerer med jQuery.

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

produksjon:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'
Svarte 20/08/2012 kl. 07:36
kilden bruker

stemmer
23

Etter siste testene kan jeg anbefale raskest og helt kryss nettleser kompatibel innfødte javascript (DOM) løsning:

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

Hvis du gjentar det mange ganger kan du gjøre det med variabler gang forberedt:

//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
}

Se på min siste opptreden sammenligning ( stack spørsmålet ).

Svarte 09/07/2013 kl. 10:44
kilden bruker

stemmer
15

Jeg har forbedret mustache.js eksempel tilsetning av escapeHTML()metoden til strengen objektet.

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

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

På den måten er det ganske enkelt å bruke "Some <text>, more Text&Text".escapeHTML()

Svarte 22/11/2012 kl. 10:20
kilden bruker

stemmer
15

escape()og unescape()er ment å kode / dekode strenger for webadresser, ikke HTML.

Egentlig bruker jeg følgende kodebit å gjøre triks som ikke krever noen rammeverk:

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');
Svarte 25/05/2012 kl. 12:39
kilden bruker

stemmer
10

Hvis du har underscore.js bruke _.escape(mer effektiv enn jQuery-metoden postet ovenfor):

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe
Svarte 04/09/2014 kl. 17:15
kilden bruker

stemmer
5

Hvis din kommer regex rute, det er en feil i tghw er eksempelet ovenfor.

<!-- 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]]);
}
Svarte 21/05/2011 kl. 21:18
kilden bruker

stemmer
4

Dette er en fin trygt eksempel ...

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;
    }
}
Svarte 31/10/2012 kl. 01:08
kilden bruker

stemmer
3

Du kan enkelt gjøre det med vanilje js.

Bare legge til en tekst node dokumentet. Det vil bli rømt av nettleseren.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)
Svarte 29/01/2015 kl. 16:34
kilden bruker

stemmer
2
(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));
    };
})();

Ingen globale variabler, noe minne optimalisering. bruk:

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

Resultatet er:

"some&lt;tag&gt;and&amp;symbol&copy;"
Svarte 13/05/2013 kl. 11:21
kilden bruker

stemmer
1

Vanlig Java rømmer eksempel:

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;"
Svarte 11/10/2017 kl. 09:52
kilden bruker

stemmer
1

2 enkle metoder som krever NO jquery ...

Du kan kode alle tegn i strengen din slik ut:

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

Eller bare målrette hovedpersonene å bekymre seg for &, linjeskift, <, >, "og 'som:

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>

Svarte 26/07/2015 kl. 14:02
kilden bruker

stemmer
1
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);
}
Svarte 27/06/2012 kl. 15:15
kilden bruker

stemmer
0
function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

fungerer som en sjarm

Svarte 03/06/2013 kl. 02:48
kilden bruker

stemmer
0

Dette svaret gir jQuery og normal JS metoder, men dette er korteste uten å bruke DOM:

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

Rømt streng: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

Hvis den rømte mellomrom bry deg, prøv:

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

Rømt streng: It%27s %3E 20%25 less complicated this way.

Dessverre er den escape()funksjonen ble foreldet i Javascript versjon 1.5 . encodeURI()eller encodeURIComponent()er alternativer, men de overser ', så den siste linjen med kode ville slå inn i dette:

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

Alle de store nettleserne fortsatt støtter kort kode, og gitt antall gamle nettsteder, jeg tviler på at vil endre seg snart.

Svarte 18/09/2012 kl. 08:45
kilden bruker

stemmer
-2

Alle løsninger er ubrukelig hvis du ikke forhindre re-flukt, for eksempel de fleste løsninger vil holde rømmer &til &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] + ";";
        }
    ) : "";
};
Svarte 26/05/2015 kl. 19:52
kilden bruker

stemmer
-2

Hvis du lagrer denne informasjonen i en database , er det galt å rømme HTML ved hjelp av en klient-side script, bør dette gjøres i serveren . Ellers er det enkelt å omgå XSS beskyttelse.

For å gjøre mitt poeng klart, her er en exemple ved hjelp av én av svarene:

La oss si du bruker funksjonen escapeHtml å unnslippe Html fra en kommentar i bloggen din, og deretter legger det til serveren din.

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

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

Den kunne bruker:

  • Rediger POST-forespørsel parametre og erstatte kommentaren med javascript-kode.
  • Skrive den escapeHtml funksjonen via nettleseren konsollen.

Hvis brukeren lime inn denne biten inn i konsollen ville omgå XSS validering:

function escapeHtml(string){
   return string
}
Svarte 06/03/2015 kl. 18:55
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more