Posso escapar de caracteres especiais html em javascript?


Respostas:


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

11
Por que "& # 039;" e não "" ?
sereda


2
Penso que expressões regulares em replace()chamadas são desnecessárias. Seqüências de caracteres simples de caracteres antigos simples também serviriam.
Jamix

22
@jamix Você não pode fazer uma substituição global por strings brutas, enquanto os modernos mecanismos de navegador otimizam bastante a expressão regular simples.
bjornd

5
existe alguma API padrão ou esta é a única maneira?
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;'>


Trabalhando aqui, mas não trabalhando para mim offline no navegador

48

Você pode usar a .text()função do jQuery .

Por exemplo:

http://jsfiddle.net/9H6Ch/

Na documentação do jQuery referente à .text()função:

Precisamos estar cientes de que esse método escapa à string fornecida conforme necessário para que seja renderizada corretamente em HTML. Para fazer isso, ele chama o método DOM .createTextNode (), não interpreta a sequência como HTML.

As versões anteriores da documentação do jQuery escreveram da seguinte maneira ( ênfase adicionada ):

Precisamos estar cientes de que esse método escapa à string fornecida conforme necessário para que seja renderizada corretamente em HTML. Para fazer isso, ele chama o método DOM .createTextNode (), que substitui caracteres especiais pelos seus equivalentes de entidade HTML (como & lt; for <).


3
Você ainda pode usá-lo em um novo elemento se você quiser apenas converter assim: const str = "foo<>'\"&"; $('<div>').text(str).html()rendimentosfoo&lt;&gt;'"&amp;
amoebe

28

Acho que encontrei a maneira correta de fazer isso ...

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

Eu aprendi algo novo sobre HTML hoje. w3schools.com/jsref/met_document_createtextnode.asp .
Sellorio 27/06

1
Esteja ciente de que o conteúdo do nó de texto não é escapado se você tentar acessá-lo assim:document.createTextNode("<script>alert('Attack!')</script>").textContent
maechler

Esta é a maneira correta se tudo o que você está fazendo é definir texto. Isso também é textContent, mas aparentemente não é bem suportado. Isso não funcionará, no entanto, se você estiver construindo uma string com algumas partes de texto com algum html, precisará escapar ainda.
Jgmjgm 16/10/19


20

Esta é, de longe, a maneira mais rápida que eu já vi. Além disso, ele faz tudo sem adicionar, remover ou alterar elementos na página.

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

7
Aviso: não escapa aspas, portanto você não pode usar a saída dentro dos valores de atributo no código HTML. Por exemplo var divCode = '<div data-title="' + escapeHTML('Jerry "Bull" Winston') + '">Div content</div>', produzirá HTML inválido!
Izogfif 17/07/19

17

Foi interessante encontrar uma solução melhor:

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

Não analiso >porque não quebra o código XML / HTML no resultado.

Aqui estão os benchmarks: http://jsperf.com/regexpairs Além disso, criei uma escapefunção universal : http://jsperf.com/regexpairs2


1
É interessante ver que o uso do comutador é significativamente mais rápido que o mapa. Eu não esperava isso! Obrigado por compartilhar!
Peter T.

Há muito mais caracteres unicode do que você poderia codificar e levar em consideração. Eu não recomendaria este método manual.
vsync 13/06

Por que você escaparia de caracteres de vários bytes? Basta usar UTF-8 em qualquer lugar.
Neonit

4
Ignorar> pode potencialmente quebrar o código. Você deve ter em mente que dentro do <> também há html. Nesse caso, pular> será interrompido. Se você estiver escapando apenas entre as tags, provavelmente precisará apenas de escape <e &.
Jgmjgm #

8

A maneira mais concisa e com melhor desempenho de exibir texto não codificado é usar textContentproperty.

Mais rápido que usar innerHTML. E isso sem levar em conta escapar de sobrecarga.

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


@ZzZombo, é completamente normal que ele não funcione com tags de estilo e script. Ao adicionar conteúdo a eles, você adiciona código , não texto , e usa o innerHTML nesse caso. Além disso, você não precisa escapar, essas são duas tags especiais que não são analisadas como HTML. Ao analisar, seu conteúdo é tratado como texto até que a sequência de fechamento </seja atendida.
usuário

6

Os elementos DOM suportam a conversão de texto em HTML, atribuindo a innerText . innerText não é uma função, mas atribuir a ela funciona como se o texto tivesse escapado.

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

1
Pelo menos no Chrome, a atribuição de texto <br>de múltiplas linhas adiciona elementos no lugar de novas linhas, que podem quebrar certos elementos, como estilos ou scripts. O createTextNodenão é propenso a esse problema.
ZzZombo

1
innerTexttem alguns problemas de legado / especificação. Melhor usar textContent.
Roy Tinker

3

Você pode codificar todos os caracteres da sua string:

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

Ou apenas alveje os personagens principais com os quais se preocupar (&, inebreaks, <,>, "e ') como:

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>


Escrever sua própria função de escape geralmente é uma má ideia. Outras respostas são melhores nesse sentido.
1113

2

Uma linha (para ES6 +):

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

Para versões mais antigas:

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

0

Me deparei com esse problema ao criar uma estrutura DOM. Esta pergunta me ajudou a resolvê-lo. Eu queria usar uma divisa dupla como separador de caminho, mas o acréscimo de um novo nó de texto resultou diretamente na exibição do código de caractere de escape, em vez do próprio caractere:

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 você já usa módulos no seu aplicativo, pode usar o módulo escape-html .

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


-4

Eu vim com esta solução.

Vamos supor que queremos adicionar algum html ao elemento com dados não seguros do usuário ou banco de dados.

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

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

element.html(html);

Não é seguro contra ataques XSS. Agora adicione isso.

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

Então é

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

Para mim, isso é muito mais fácil do que usar .replace()e será removido !!! todas as tags html possíveis (espero).


Se for uma idéia perigosa, ele analisa a String HTML insegura como HTML; se o elemento fosse anexado ao DOM, ele sairia. use .innerText.
precisa saber é o seguinte

Isso não é seguro. Ele se converte &lt;script&gt;em <script>.
fgb
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.