2010-11-01 6 views
9

Il se sent comme html_safe ajoute une abstraction à la classe String qui exige la compréhension de ce qui se passe, par exemple,Pourquoi dans Rails 3, <% = note.html_safe%> et <% = h note.html_safe%> donnent le même résultat?

<%= '1 <b>2</b>' %>  # gives 1 &lt;b&gt;2&lt;/b&gt; in the HTML source code 

<%= h '1 <b>2</b>' %> # exactly the same as above 

<%= '1 <b>2</b>'.html_safe %>  # 1 <b>2</b> in HTML source code 

<%= h '1 <b>2</b>'.html_safe %> # exactly the same as above 

<%= h (h '1 <b>2</b>') %> # 1 &lt;b&gt;2&lt;/b&gt; wont' escape twice 

Pour la ligne 4, si nous disons, ok, nous faisons confiance à la chaîne - il est sûr, mais pourquoi ne pouvons-nous pas y échapper? Il semble que pour l'échapper par h, la chaîne doit être dangereuse.

Donc sur la ligne 1, si la chaîne n'est pas échappée par h, elle sera automatiquement échappée. Sur la ligne 5, h ne peut pas échapper la chaîne deux fois - en d'autres termes, après < est changé en &lt;, il ne peut pas l'échapper une fois de plus à &amp;lt;.

Alors, que se passe-t-il? Au début, je pensais que html_safe est juste de marquer un drapeau à la chaîne, en disant qu'il est sûr. Alors, pourquoi h ne lui échappe pas? Il semble que h et html_escape effectivement coopèrent sur l'utilisation du drapeau:

1) Si une chaîne est html_safe, alors h n'y échappera pas

2) Si une chaîne n'est pas html_safe, puis quand la chaîne est ajouté au tampon de sortie, il sera automatiquement échappé par h.

3) Si h a déjà échappé à une chaîne, il est marqué html_safe, et donc, l'échapper une fois de plus par h ne prendra aucun effet. (comme sur la ligne 5, et ce comportement est le même même dans Rails 2.3.10, mais sur Rails 2.3.5 h peut effectivement lui échapper deux fois ... donc dans Rails 2.3.5, h est une méthode d'échappement simple, mais certains où le long de la ligne vers 2.3.10, h n'est pas devenu aussi simple mais 2.3.10 n'échappera pas automatiquement à une chaîne, mais pour une raison quelconque, la méthode html_safe existe déjà pour 2.3.10 (dans quel but?))

Est-ce ainsi que ça fonctionne exactement? Je pense qu'aujourd'hui, parfois nous n'obtenons pas ce que nous voulons dans la sortie et nous ajoutons immédiatement html_safe à notre variable, ce qui peut être assez dangereux, car cela peut introduire une attaque XSS de cette façon, donc comprendre comment cela fonctionne exactement peut être très important . Ce qui précède est seulement une supposition de comment cela fonctionne exactement. Pourrait-il s'agir d'un mécanisme différent et existe-t-il un document qui le supporte?

Répondre

6

Comme vous pouvez le voir, appeler html_safe sur une chaîne se transforme en un html sûr SafeBuffer

http://github.com/rails/rails/blob/89978f10afbad3f856e2959a811bed1982715408/activesupport/lib/active_support/core_ext/string/output_safety.rb#L87

Toute opération sur un SafeBuffer qui pourraient avoir une incidence sur la sécurité de la chaîne sera passé par h()

h utilise cet indicateur pour éviter le double échappement

http://github.com/rails/rails/blob/89978f10afbad3f856e2959a811bed1982715408/activesupport/lib/active_support/core_ext/string/output_safety.rb#L18

Le comportement a changé et je pense que vous avez surtout raison sur la façon dont cela fonctionne. En général, vous ne devez pas appeler html_safe sauf si vous êtes sûr qu'il est déjà nettoyé.Comme quoi que ce soit, il faut être prudent en utilisant

+1

intéressant ... il utilise une nouvelle classe SafeBuffer comme "flag" ... donc '' foobar ".html_safe' va réellement créer et retourner une nouvelle instance de SafeBuffer avec le contenu de la chaîne d'origine ... –

Questions connexes