Comment encoder / échapper en HTML une chaîne? Y a-t-il un intégré?

98

J'ai une chaîne non approuvée que je souhaite afficher sous forme de texte dans une page HTML. J'ai besoin d'échapper aux caractères ' <' et '& » en tant qu'entités HTML. Moins il y a de bruit, mieux c'est.

J'utilise UTF8 et je n'ai pas besoin d'autres entités pour les lettres accentuées.

Existe-t-il une fonction intégrée dans Ruby ou Rails, ou devrais-je utiliser la mienne?

kch
la source
2
Selon l'OWASP , les six caractères suivants doivent être échappés pour une protection XSS appropriée dans le contenu des éléments HTML:&<>"'/
sffc

Réponses:

94

La hméthode d'assistance:

<%=h "<p> will be preserved" %>
Trevor Bramble
la source
Eh bien, cela s'échappe également>, ce qui n'est pas nécessaire, mais cela fera l'affaire.
kch
Vous pouvez utiliser des parenthèses pour en imprimer certaines avec h et d'autres sans. <% = h ("<p") + ">"%>
Trevor Bramble
Maintenant, ce serait idiot. Je me fiche de savoir s'il s'échappe ou non. Je note simplement que ce n'est pas obligatoire selon les spécifications html.
kch
12
Il est parfois nécessaire dans XHTML en raison de l'insistance plutôt ennuyeuse de la spécification XML pour que ']]>' ne soit pas contenu dans le texte (voir la production de 'CharData'). Cela rend généralement plus facile (et inoffensif) de toujours y échapper.
bobince
19
pour ceux qui sont intéressés hest un alias pourhtml_escape
lightswitch05
141

Consultez la classe Ruby CGI . Il existe des méthodes pour encoder et décoder le HTML ainsi que les URL.

CGI::escapeHTML('Usage: foo "bar" <baz>')
# => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
Christopher Bradford
la source
12
Merci, c'est génial car cela peut être fait à partir des contrôleurs. Non pas que je ferais ça, bien sûr.
Dan Rosenstark le
2
Ceci est utile dans les tests fonctionnels / d'intégration, pour vérifier l'exactitude du contenu inséré dans un modèle (lorsque le contenu est supposé être échappé au HTML).
Alex D
Si le contenu est affiché sur le site Web d'un client, autre que le vôtre (où vous ne pouvez pas contrôler la vue), quel est le problème d'échapper au code HTML avant de l'insérer dans la base de données? Y a-t-il un autre travail autour?
n00b
Droite - s'échapper avant d'entrer dans la base de données est génial. Vous voulez juste vous assurer de ne pas avoir de vieux hacks non échappés avant de l'ajouter ...
Kevin
5
J'aime plus son synonyme: CGI.escape_html
Trantor Liu
77

Dans Ruby on Rails 3, le HTML sera échappé par défaut.

Pour les chaînes non échappées, utilisez:

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

ERB :: Util.html_escape peut être utilisé n'importe où. Il est disponible sans utilisation requiredans Rails.

Viktor Trón
la source
ceci utilise en fait en CGI.escapeHTMLdessous
akostadinov
@akostadinov - le résultat est cependant différent. Par exemple, ERB :: Util.html_escape transformera les apostrophes en & # x27; alors que CGI :: escapeHTML ne le fera pas
Louis Sayers
@LouisSayers, je ne vois pas comment cela peut arriver: `` `` [43] pry (main)> show-source ERB :: Util.html_escape From: /usr/share/ruby/erb.rb @ line 945: Owner : # <Class: ERB :: Util> Visibilité: public Nombre de lignes: 3 def html_escape (s) CGI.escapeHTML (s.to_s) end `` ``
akostadinov
@akostadinov - hmm ... Je viens de courir à nouveau et oui, ils ont produit le même résultat. Je jure que cela a produit des résultats différents lorsque j'ai exécuté cela au travail (peut-être un comportement de version erb / cgi différent?). Je vais devoir voir pourquoi j'ai un résultat différent au travail demain.
Louis Sayers
17

Un ajout à la réponse de Christopher Bradford pour utiliser l'échappement HTML n'importe où, puisque la plupart des gens ne l'utilisent pas de CGInos jours, vous pouvez également utiliser Rack:

require 'rack/utils'
Rack::Utils.escape_html('Usage: foo "bar" <baz>')
J -_- L
la source
Existe-t-il un meilleur moyen d'échapper des chaînes de manière similaire dans les méthodes d'instance de modèle?
Codage actif le
15

Vous pouvez utiliser soit h()ou html_escape(), mais la plupart des gens utilisent h()par convention. h()est l'abréviation de html_escape()in rails.

Dans votre contrôleur:

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

À votre avis:

<%=h @stuff %>

Si vous affichez la source HTML: vous verrez la sortie sans réellement mettre les données en gras. C'est-à-dire qu'il est codé comme &lt;b&gt;Hello World!&lt;/b&gt;.

Il apparaîtra et sera affiché comme <b>Hello World!</b>

Brian R. Bondy
la source
9

Comparaison des différentes méthodes:

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

J'ai écrit le mien pour être compatible avec l'échappement Rails ActiveMailer:

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

h() est également utile pour échapper des guillemets.

Par exemple, j'ai une vue qui génère un lien à l'aide d'un champ de texte result[r].thtitle. Le texte peut inclure des guillemets simples. Si je ne m'échappais pas result[r].thtitledans la méthode de confirmation, le Javascript se briserait:

&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>

Remarque: la :htmldéclaration de titre est magiquement échappée par Rails.

Noddinoff
la source