raw vs. html_safe vs. h to unescape html

323

Załóżmy, że mam następujący ciąg

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

Moim zdaniem chcę, aby link był wyświetlany. Oznacza to, że nie chcę, aby wszystko w @x było nieskalowane i wyświetlane jako ciąg. Jaka jest różnica między używaniem

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

?

grautur
źródło
Ponieważ nikt o tym nie wspominał, pomyślałem, że wspomnę również, że istnieje <%== @x %>alias <%= raw(@x) %> edgeguides.rubyonrails.org/…
CTS_AE

Odpowiedzi:

386

Biorąc pod uwagę szyny 3:

html_safew rzeczywistości „ustawia ciąg” jako Bezpieczny HTML (jest to trochę bardziej skomplikowane, ale w zasadzie to jest to). W ten sposób możesz dowolnie zwracać ciągi znaków Bezpieczne HTML od pomocników lub modeli.

hmoże być używany tylko z poziomu kontrolera lub widoku, ponieważ pochodzi od pomocnika. Zmusi to wyjście do ucieczki. Nie jest tak naprawdę przestarzałe, ale najprawdopodobniej już go nie użyjesz: jedynym sposobem jest „przywrócenie” html_safedeklaracji, co jest dość niezwykłe.

Przygotowanie wyrażenia za pomocą w rawrzeczywistości jest równoważne wywołaniu to_społączonemu z html_safenim, ale jest zadeklarowane w pomocniku, podobnie jak h, więc można go używać tylko w kontrolerach i widokach.

SafeBuffers and Rails 3.0 ” to miłe wytłumaczenie tego, jak działa SafeBuffers (klasa, która wykonuje html_safemagię).

Fábio Batista
źródło
42
Nie powiedziałbym, że hto będzie przestarzałe. Używanie "Hi<br/>#{h@ user.name}".html_safejest dość powszechne i akceptowane.
maletor
1
@Maletor ciekawe zastosowanie, choć nadal uważam, że należy ono do kategorii „niezwykłych”.
Fábio Batista
5
Ciąg # html_safe faktycznie zwraca instancję ActiveSupport :: SafeBuffer, która otacza oryginalny ciąg i ma #html_safe? . Oryginalny ciąg nie staje się #html_safe? po wywołaniu na nim #html_safe.
jmaxyz
9
Zauważ, że istnieje subtelna różnica między rawi html_safew praktyce: raw(nil)zwraca pusty ciąg, a nil.html_safezgłasza wyjątek.
Van der Hoorn,
2
hnie „przywróci” deklaracji html_safe. Gdy łańcuch jest html_safe, hnic nie zrobi.
GuiGS
113

Myślę, że to wyraźnie podkreślić: html_safenie nie HTML-uciec swój ciąg. W rzeczywistości zapobiegnie to ucieczce łańcucha.

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

położy:

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

do twojego źródła HTML (tak, więc bezpiecznie!), a jednocześnie:

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

pojawi się okno dialogowe alertu (jesteś pewien, że tego właśnie chcesz?). Prawdopodobnie nie chcesz wywoływać html_safeżadnych ciągów wprowadzonych przez użytkownika.

skurcz
źródło
81
Innymi słowy, html_safe to nie „proszę, uczyń ten HTML bezpiecznym”, wręcz przeciwnie - to ty programista mówi szykom, że „ten ciąg jest bezpieczny HTML, obiecuj!”
PaulMurrayCbr
tak naprawdę przyszedłem tutaj, aby dowiedzieć się, czy faktycznie robi to rozpakowywanie, czy też po prostu zaznacza, że ​​nie jest konieczne przeglądanie . Całkiem różnica. No cóż, więc czytaj dalej kod źródłowy.
Simon B.
Pojęcie „html_safe” jest po prostu meta flagą w ciągu. Znakowanie coś jak html_safema nie uciekać ani unescape. Choć wynik końcowy oznaczania coś co nie HTML bezpieczne, a następnie przy użyciu niejawny cytowanie ERB <% = znacznika, może być taka sama jak unescaping danych, a następnie ponownie go uciekając na wyjściu, funkcjonalnie to robi ani. Coś jak różnica (6 * -1 * -1), w porównaniu z 6.
Ben Zittlau
46

Różnica polega między Railsami html_safe()a raw(). Jest na ten temat świetny post Yehuda Katza, który naprawdę sprowadza się do tego:

def raw(stringish)

  stringish.to_s.html_safe

end

Tak, raw()jest otoczką, html_safe()która wymusza wejście do String, a następnie wywołuje html_safe()ją. Jest tak również w przypadku raw()pomocnika w module, podczas gdy html_safe()jest to metoda klasy String, która tworzy nową instancję ActiveSupport :: SafeBuffer - która ma@dirty flagą.

Zobacz sekcjęRails 'html_safe vs. raw ”.

Pankhuri
źródło
30
  1. html_safe :

    Oznacza ciąg jako zaufany bezpieczny. Zostanie on wstawiony do HTML bez wykonywania dodatkowych znaków zmiany znaczenia.

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

    rawto tylko opakowanie html_safe. Użyj, rawjeśli istnieją szanse, że będzie ciąg nil.

    raw("<a>Hello</a>")
    #=> "<a>Hello</a>"
    
    raw(nil)
    #=> ""
  3. h alias dla html_escape :

    Metoda narzędziowa do zmiany znaczenia znaczników HTML. Użyj tej metody, aby uniknąć niebezpiecznych treści.

    W Railsach 3 i nowszych jest on używany domyślnie, więc nie musisz jawnie używać tej metody

Deepak Mahakale
źródło
14

Najlepszym bezpiecznym sposobem jest: <%= sanitize @x %>

Pozwoli to uniknąć XSS!

Guilherme Y. Hatano
źródło
2

W prostych słowach:

h usuń tagi html na znaki liczbowe, aby renderowanie nie uszkodziło html

html_safe ustawia ciąg boolean w taki sposób, aby traktowany był jako zapis html

raw Konwertuje na html_safe na string

użytkownik3118220
źródło
hjest html_safe, co oznacza, że ​​HTML jest renderowany „tak jak jest”.
Dave Newton
Odpowiedź jest poprawna: h to html_escape ... z bazy kodu Rails
notapatch