¿Cómo codificar HTML / escapar de una cadena? ¿Hay uno incorporado?

98

Tengo una cadena que no es de confianza que quiero mostrar como texto en una página HTML. Necesito escapar de los caracteres <"y &" como entidades HTML. Cuanto menos alboroto, mejor.

Estoy usando UTF8 y no necesito otras entidades para letras acentuadas.

¿Hay una función incorporada en Ruby o Rails, o debería usar la mía propia?

kch
fuente
2
De acuerdo con OWASP , los siguientes seis caracteres deben escaparse para una protección XSS adecuada en el contenido del elemento HTML:&<>"'/
sffc

Respuestas:

94

El hmétodo de ayuda:

<%=h "<p> will be preserved" %>
Trevor Bramble
fuente
Bueno, también escapa>, lo cual es innecesario, pero servirá.
kch
Puede utilizar paréntesis para imprimir algunos con h y otros sin. <% = h ("<p") + ">"%>
Trevor Bramble
Eso sería una tontería. No me importa mucho si se escapa o no. Solo estoy señalando que no es obligatorio según las especificaciones html.
kch
12
Es ocasionalmente necesario en XHTML debido a la insistencia bastante molesto de la especificación XML que ']]>' debe mantenerse fuera del texto (ver la producción 'CharData'). Esto hace que en general sea más fácil (e inofensivo) escapar siempre.
Bobince
19
para los interesados hes un alias parahtml_escape
lightswitch05
141

Consulte la clase Ruby CGI . Existen métodos para codificar y decodificar HTML y URL.

CGI::escapeHTML('Usage: foo "bar" <baz>')
# => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
Christopher Bradford
fuente
12
Gracias, esto es genial ya que se puede hacer desde los controladores. No es que yo haría eso, por supuesto.
Dan Rosenstark
2
Esto es útil en pruebas funcionales / de integración, para verificar la exactitud del contenido insertado en una plantilla (cuando se supone que el contenido tiene formato HTML).
Alex D
Si el contenido se muestra en el sitio web de un cliente, que no sea el suyo (donde no puede controlar la vista), ¿cuál es el problema de escapar del html antes de insertarlo en la base de datos? ¿Hay otra solución?
n00b
Correcto: escapar antes de ingresar a la base de datos es genial. Solo desea asegurarse de no tener ningún truco antiguo que no haya escapado antes de agregarlo ...
Kevin
5
Me gusta más su sinónimo: CGI.escape_html
Trantor Liu
77

En Ruby on Rails 3, HTML se escapará de forma predeterminada.

Para cadenas sin escape, utilice:

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

ERB :: Util.html_escape se puede utilizar en cualquier lugar. Está disponible sin usar requireen Rails.

Viktor Trón
fuente
esto en realidad está usando CGI.escapeHTMLdebajo
akostadinov
@akostadinov - sin embargo, el resultado es diferente. Por ejemplo, ERB :: Util.html_escape convertirá los apóstrofos en & # x27; mientras que CGI :: escapeHTML no lo hará
Louis Sayers
@LouisSayers, no veo cómo puede suceder eso: `` `[43] pry (main)> show-source ERB :: Util.html_escape From: /usr/share/ruby/erb.rb @ line 945: Owner : # <Clase: ERB :: Util> Visibilidad: público Número de líneas: 3 def html_escape (s) CGI.escapeHTML (s.to_s) end `` `
akostadinov
@akostadinov - hmm ... Acabo de ejecutar de nuevo y sí, produjeron el mismo resultado. Juro que esto produjo resultados diferentes cuando ejecuté esto en el trabajo (¿quizás un comportamiento diferente de la versión erb / cgi?). Mañana tendré que ver por qué obtuve un resultado diferente en el trabajo.
Louis Sayers
17

Una adición a la respuesta de Christopher Bradford para usar el escape HTML en cualquier lugar, dado que la mayoría de la gente no lo usa CGIhoy en día, también puede usar Rack:

require 'rack/utils'
Rack::Utils.escape_html('Usage: foo "bar" <baz>')
J -_- L
fuente
¿Existe una mejor manera de escapar de las cadenas de forma similar en los métodos de instancia del modelo?
Codificación activa el
15

Puede usar h()o html_escape(), pero la mayoría de la gente lo usa h()por convención. h()es la abreviatura de html_escape()rieles.

En tu controlador:

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

En tu opinión:

<%=h @stuff %>

Si ve la fuente HTML: verá la salida sin poner los datos en negrita. Es decir, está codificado como &lt;b&gt;Hello World!&lt;/b&gt;.

Aparecerá y se mostrará como <b>Hello World!</b>

Brian R. Bondy
fuente
9

Comparación de los 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;"

Escribí el mío para que sea compatible con el escape de Rails ActiveMailer:

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

h() también es útil para escapar de las comillas.

Por ejemplo, tengo una vista que genera un enlace usando un campo de texto result[r].thtitle. El texto puede incluir comillas simples. Si no escapara result[r].thtitleen el método de confirmación, el Javascript se rompería:

&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: :htmlRails escapa mágicamente de la declaración del título.

Noddinoff
fuente