Como codificar / escapar HTML de uma string? Existe um embutido?

98

Eu tenho uma string não confiável que quero mostrar como texto em uma página HTML. Eu preciso escapar os caracteres ' <' e ' &' como entidades HTML. Quanto menos barulho, melhor.

Estou usando UTF8 e não preciso de outras entidades para letras acentuadas.

Existe uma função embutida no Ruby ou Rails, ou devo lançar a minha própria?

kch
fonte
2
De acordo com o OWASP , os seguintes seis caracteres devem ser escapados para proteção XSS adequada no conteúdo do elemento HTML:&<>"'/
sffc

Respostas:

94

O hmétodo auxiliar:

<%=h "<p> will be preserved" %>
Trevor Bramble
fonte
Bem, também escapa>, o que é desnecessário, mas servirá.
kch
Você pode usar parênteses para imprimir alguns com he outros sem. <% = h ("<p") + ">"%>
Trevor Bramble
Agora, isso seria bobo. Não me importo muito se escapou ou não. Estou apenas observando que não é obrigatório pelas especificações de html.
kch
12
Ocasionalmente, é necessário em XHTML devido à insistência um tanto irritante das especificações XML de que ']]>' seja mantido fora do texto (veja a produção de 'CharData'). Isso torna geralmente mais fácil (e inofensivo) sempre escapar dela.
bobince
19
para os interessados, hum alias parahtml_escape
lightswitch05
141

Verifique a classe Ruby CGI . Existem métodos para codificar e decodificar HTML, bem como URLs.

CGI::escapeHTML('Usage: foo "bar" <baz>')
# => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
Christopher Bradford
fonte
12
Obrigado, isso é ótimo, pois pode ser feito a partir dos controladores. Não que eu fizesse isso, é claro.
Dan Rosenstark,
2
Isso é útil em testes funcionais / de integração, para verificar a exatidão do conteúdo inserido em um modelo (quando o conteúdo deveria ter escape de HTML).
Alex D de
Se o conteúdo está sendo exibido em um site de cliente, outro que não o seu (onde você não pode controlar a visualização), qual é o problema em escapar do html antes de inserir no banco de dados? Existe outra solução alternativa?
n00b
É ótimo escapar antes de entrar no banco de dados. Você só quer ter certeza de que não há nenhum hacks antigo não escapado antes de adicioná-lo ...
Kevin
5
Gosto mais do sinônimo: CGI.escape_html
Trantor Liu
77

No Ruby on Rails 3, o HTML será escapado por padrão.

Para strings sem escape, use:

<%= raw "<p>hello world!</p>" %>
RSK
fonte
25

ERB :: Util.html_escape pode ser usado em qualquer lugar. Ele está disponível sem usar requireno Rails.

Viktor Trón
fonte
na verdade está usando CGI.escapeHTMLembaixo
akostadinov
@akostadinov - o resultado é diferente no entanto. Por exemplo, ERB :: Util.html_escape transformará apóstrofos em & # x27; enquanto CGI :: escapeHTML não
Louis Sayers
@LouisSayers, não consigo ver como isso pode acontecer: `` `[43] pry (main)> show-source ERB :: Util.html_escape De: /usr/share/ruby/erb.rb @ linha 945: Proprietário : # <Class: ERB :: Util> Visibilidade: public Número de linhas: 3 def html_escape (s) CGI.escapeHTML (s.to_s) end `` `
akostadinov
@akostadinov - hmm ... Apenas executei novamente e sim, eles produziram a mesma saída. Juro que isso produziu resultados diferentes quando o executei no trabalho (talvez comportamento diferente da versão erb / cgi?). Terei que ver por que consegui um resultado diferente no trabalho amanhã.
Louis Sayers
17

Além da resposta de Christopher Bradford para usar o escape HTML em qualquer lugar, já que a maioria das pessoas não usa CGIhoje em dia, você também pode usar Rack:

require 'rack/utils'
Rack::Utils.escape_html('Usage: foo "bar" <baz>')
J -_- L
fonte
Existe uma maneira melhor de escapar strings de maneira semelhante em métodos de instância de modelo?
Codificação ativa em
15

Você pode usar h()ou html_escape(), mas a maioria das pessoas usa h()por convenção. h()é a abreviação de html_escape()in rails.

Em seu controlador:

@stuff = "<b>Hello World!</b>"

Em sua opinião:

<%=h @stuff %>

Se você visualizar o código-fonte HTML: verá a saída sem realmente colocar os dados em negrito. Ou seja, está codificado como &lt;b&gt;Hello World!&lt;/b&gt;.

Ele aparecerá e será exibido como <b>Hello World!</b>

Brian R. Bondy
fonte
9

Comparação dos diferentes métodos:

> CGI::escapeHTML("quote ' double quotes \"")
=> "quote &#39; double quotes &quot;"

> Rack::Utils.escape_html("quote ' double quotes \"")
=> "quote &#x27; double quotes &quot;"

> ERB::Util.html_escape("quote ' double quotes \"")
=> "quote &#39; double quotes &quot;"

Eu escrevi meu próprio para ser compatível com o escape de Rails ActiveMailer:

def escape_html(str)
  CGI.escapeHTML(str).gsub("&#39;", "'")
end
Dorian
fonte
0

h() também é útil para escapar de aspas.

Por exemplo, tenho um modo de exibição que gera um link usando um campo de texto result[r].thtitle. O texto pode incluir aspas simples. Se eu não escapar result[r].thtitleno método de confirmação, o Javascript irá quebrar:

&lt;%= link_to_remote "#{result[r].thtitle}", :url=>{ :controller=>:resource,
:action         =>:delete_resourced,
:id     => result[r].id,
:th     => thread,                                                                                                      
:html       =>{:title=> "<= Remove"},                                                       
:confirm    => h("#{result[r].thtitle} will be removed"),                                                   
:method     => :delete %>

&lt;a href="#" onclick="if (confirm('docs: add column &amp;apos;dummy&amp;apos; will be removed')) { new Ajax.Request('/resource/delete_resourced/837?owner=386&amp;th=511', {asynchronous:true, evalScripts:true, method:'delete', parameters:'authenticity_token=' + encodeURIComponent('ou812')}); }; return false;" title="&lt;= Remove">docs: add column 'dummy'</a>

Nota: a :htmldeclaração do título é escapada magicamente pelo Rails.

Noddinoff
fonte