raw vs html_safe vs h pour annuler l'échappement html

323

Supposons que j'ai la chaîne suivante

@x = "<a href='#'>Turn me into a link</a>"

À mon avis, je veux qu'un lien soit affiché. Autrement dit, je ne veux pas que tout dans @x soit échappé et affiché sous forme de chaîne. Quelle est la différence entre l'utilisation

<%= raw @x %>
<%= h @x %>
<%= @x.html_safe %>

?

grautur
la source
Puisque personne ne l'a mentionné, j'ai pensé que je mentionnerais également qu'il y a <%== @x %>un alias à <%= raw(@x) %> edgeguides.rubyonrails.org/…
CTS_AE

Réponses:

386

Considérant Rails 3:

html_safeen fait "définit la chaîne" comme HTML Safe (c'est un peu plus compliqué que ça, mais c'est fondamentalement ça). De cette façon, vous pouvez renvoyer des chaînes HTML Safe à partir d'aides ou de modèles à volonté.

hne peut être utilisé qu'à partir d'un contrôleur ou d'une vue, car il provient d'un assistant. Cela forcera la sortie à s'échapper. Ce n'est pas vraiment obsolète, mais vous ne l'utiliserez probablement plus: le seul usage est de "revenir" à une html_safedéclaration, ce qui est assez inhabituel.

Ajouter votre expression avec rawéquivaut en fait à appeler to_schaîné avec html_safe, mais est déclaré sur un assistant, tout comme h, il ne peut donc être utilisé que sur les contrôleurs et les vues.

" SafeBuffers and Rails 3.0 " est une belle explication sur le fonctionnement du SafeBuffers (la classe qui fait la html_safemagie).

Fábio Batista
la source
42
Je ne dirais pas que cela hsera déprécié. L'utilisation "Hi<br/>#{h@ user.name}".html_safeest assez courante et une utilisation acceptée.
maletor
1
@Maletor est une utilisation intéressante, même si je pense toujours qu'elle tombe dans la catégorie "inhabituelle".
Fábio Batista
5
La chaîne # html_safe retourne en fait une instance d'ActiveSupport :: SafeBuffer qui enveloppe la chaîne d'origine et est #html_safe? . La chaîne d'origine ne devient pas #html_safe? après avoir appelé #html_safe dessus.
jmaxyz
9
Notez qu'il existe une différence subtile entre rawet html_safedans la pratique: raw(nil)renvoie une chaîne vide, tout en nil.html_safelançant une exception.
Van der Hoorn
2
hne "rétablira" pas une déclaration html_safe. Lorsqu'une chaîne est html_safe, hne fera rien.
GuiGS
113

Je pense que cela mérite d'être répété: html_safen'échappe pas à votre chaîne HTML. En fait, cela empêchera votre chaîne de s'échapper.

<%= "<script>alert('Hello!')</script>" %>

va mettre:

&lt;script&gt;alert(&#x27;Hello!&#x27;)&lt;/script&gt;

dans votre source HTML (oui, si sûr!), tout en:

<%= "<script>alert('Hello!')</script>".html_safe %>

fera apparaître la boîte de dialogue d'alerte (êtes-vous sûr que c'est ce que vous voulez?). Donc, vous ne voulez probablement pas appeler html_safede chaînes saisies par l'utilisateur.

roasm
la source
81
En d'autres termes, html_safe n'est pas "veuillez sécuriser ce code html", c'est le contraire - c'est vous le programmeur qui dit aux rails que "cette chaîne est sécurisée en html, promis!"
PaulMurrayCbr
en fait, je suis venu ici pour savoir si cela permet effectivement de s'échapper ou s'il marque simplement qu'il n'est pas nécessaire de_échapper . Quelle différence. Eh bien, off pour lire le code source alors.
Simon B.
Le concept de "html_safe" est juste un meta flag sur la chaîne. Marquage quelque chose comme html_safene pas échapper ni unescape. Bien que le résultat final du marquage de quelque chose comme non sûr pour HTML, puis de l'utilisation de l'échappement implicite de la balise ERB <% =, puisse être le même que l'échappement des données et leur rééchappement en sortie, fonctionnellement, il ne fait ni l'un ni l'autre. Un peu comme la différence de (6 * -1 * -1), contre 6.
Ben Zittlau
46

La différence est entre Rails html_safe()et raw(). Il y a un excellent article de Yehuda Katz à ce sujet, et cela se résume vraiment à ceci:

def raw(stringish)

  stringish.to_s.html_safe

end

Oui, raw()est un wrapper html_safe()qui force l'entrée à String et l'appelle ensuite html_safe(). C'est également le cas qui raw()est un assistant dans un module tandis html_safe()qu'une méthode sur la classe String crée une nouvelle instance ActiveSupport :: SafeBuffer - qui a un @dirtyindicateur.

Reportez-vous à " Rails 'html_safe vs. raw ".

Pankhuri
la source
30
  1. html_safe :

    Marque une chaîne comme sécurisée de confiance. Il sera inséré dans HTML sans aucun échappement supplémentaire effectué.

    "<a>Hello</a>".html_safe
    #=> "<a>Hello</a>"
    
    nil.html_safe
    #=> NoMethodError: undefined method `html_safe' for nil:NilClass
  2. raw :

    rawest juste un emballage autour html_safe. À utiliser raws'il y a des chances que la chaîne le soit nil.

    raw("<a>Hello</a>")
    #=> "<a>Hello</a>"
    
    raw(nil)
    #=> ""
  3. halias pour html_escape:

    Une méthode utilitaire pour échapper les caractères de balise HTML. Utilisez cette méthode pour échapper à tout contenu dangereux.

    Dans Rails 3 et supérieur, il est utilisé par défaut, vous n'avez donc pas besoin d'utiliser cette méthode explicitement

Deepak Mahakale
la source
14

Le meilleur moyen sûr est: <%= sanitize @x %>

Cela évitera XSS!

Guilherme Y. Hatano
la source
2

En termes de Rails simples:

h supprimer les balises html en caractères numériques afin que le rendu ne casse pas votre html

html_safe définit un booléen dans la chaîne afin que la chaîne soit considérée comme une sauvegarde html

raw Il convertit en html_safe en chaîne

user3118220
la source
his html_safe, ce qui signifie que le code HTML est rendu tel quel.
Dave Newton
La réponse est correcte: h est html_escape ... de la base de code Rails
notapatch