Bagaimana cara menyandikan / melepaskan string HTML? Apakah ada built-in?

98

Saya memiliki string tidak tepercaya yang ingin saya tampilkan sebagai teks di halaman HTML. Saya harus melepaskan karakter ' <' dan ' &' sebagai entitas HTML. Semakin sedikit keributan semakin baik.

Saya menggunakan UTF8 dan tidak memerlukan entitas lain untuk huruf beraksen.

Apakah ada fungsi bawaan di Ruby atau Rails, atau haruskah saya menggulungnya sendiri?

kch
sumber
2
Menurut OWASP , enam karakter berikut harus di-escape untuk perlindungan XSS yang tepat dalam konten elemen HTML:&<>"'/
sffc

Jawaban:

94

The hhelper Metode:

<%=h "<p> will be preserved" %>
Trevor Bramble
sumber
Yah, itu juga lolos>, yang tidak perlu, tapi itu akan berhasil.
kch
Anda dapat menggunakan tanda kurung untuk mencetak beberapa dengan h dan beberapa tanpa. <% = h ("<p") + ">"%>
Trevor Bramble
Nah, itu konyol. Saya tidak terlalu peduli apakah itu lolos atau tidak. Saya hanya mencatat itu tidak diperlukan sesuai spesifikasi html.
kch
12
Kadang- kadang diperlukan dalam XHTML karena desakan spesifikasi XML yang agak mengganggu bahwa ']]>' dijauhkan dari teks (lihat produksi 'CharData'). Hal ini umumnya membuat lebih mudah (dan tidak berbahaya) untuk selalu menghindarinya.
bobince
19
bagi mereka yang tertarik hadalah alias untukhtml_escape
lightswitch05
141

Lihat kelas Ruby CGI . Ada metode untuk menyandikan dan mendekode HTML serta URL.

CGI::escapeHTML('Usage: foo "bar" <baz>')
# => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
Christopher Bradford
sumber
12
Terima kasih, ini bagus karena dapat dilakukan dari pengontrol. Bukannya aku akan melakukannya, tentu saja.
Dan Rosenstark
2
Ini berguna dalam pengujian fungsional / integrasi, untuk memeriksa kebenaran konten yang dimasukkan ke dalam template (saat konten seharusnya di-escape dengan HTML).
Alex D
Jika konten ditampilkan di situs web klien, selain milik Anda sendiri (di mana Anda tidak dapat mengontrol tampilan), apa masalah dengan keluar dari html sebelum memasukkan ke dalam database? Apakah ada solusi lain?
n00b
Benar - melarikan diri sebelum masuk ke database itu bagus. Anda hanya ingin memastikan bahwa Anda tidak memiliki peretasan lama yang tidak lolos sebelum Anda menambahkannya ...
Kevin
5
Saya lebih suka sinonimnya: CGI.escape_html
Trantor Liu
77

Di Ruby on Rails 3 HTML akan di-escape secara default.

Untuk string non-escape, gunakan:

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

ERB :: Util.html_escape dapat digunakan dimana saja. Ini tersedia tanpa menggunakan requiredi Rails.

Viktor Trón
sumber
ini sebenarnya menggunakan di CGI.escapeHTMLbawah
akostadinov
@akostadinov - Namun hasilnya berbeda. Misalnya, ERB :: Util.html_escape akan mengubah apostrof menjadi & # x27; sedangkan CGI :: escapeHTML tidak akan
Louis Sayers
@LouisSayers, saya tidak bisa melihat bagaimana itu bisa terjadi: `` [43] pry (main)> show-source ERB :: Util.html_escape From: /usr/share/ruby/erb.rb @ line 945: Owner : # <Class: ERB :: Util> Visibility: public Jumlah baris: 3 def html_escape (s) CGI.escapeHTML (s.to_s) end ``
akostadinov
@akostadinov - hmm ... Jalankan lagi dan ya, mereka menghasilkan keluaran yang sama. Saya bersumpah ini menghasilkan hasil yang berbeda ketika saya menjalankan ini di tempat kerja (mungkin perilaku versi erb / cgi berbeda?). Saya harus melihat mengapa saya mendapat hasil yang berbeda di tempat kerja besok.
Louis Sayers
17

Selain jawaban Christopher Bradford untuk menggunakan pelolosan HTML di mana pun, karena kebanyakan orang tidak menggunakannya CGIsaat ini, Anda juga dapat menggunakan Rack:

require 'rack/utils'
Rack::Utils.escape_html('Usage: foo "bar" <baz>')
J -_- L
sumber
Apakah ada cara yang lebih baik untuk melepaskan string dengan cara yang serupa dalam metode contoh model?
Pengkodean aktif
15

Anda dapat menggunakan salah satu h()atau html_escape(), tetapi kebanyakan orang menggunakan h()berdasarkan konvensi. h()adalah kependekan dari html_escape()in rails.

Di pengontrol Anda:

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

Dalam pandangan Anda:

<%=h @stuff %>

Jika Anda melihat sumber HTML: Anda akan melihat output tanpa benar-benar menebalkan datanya. Yaitu itu dikodekan sebagai &lt;b&gt;Hello World!&lt;/b&gt;.

Ini akan muncul dan ditampilkan sebagai <b>Hello World!</b>

Brian R. Bondy
sumber
9

Perbandingan berbagai metode:

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

Saya menulis milik saya sendiri agar kompatibel dengan pelarian Rails ActiveMailer:

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

h() juga berguna untuk menghilangkan tanda kutip.

Misalnya, saya memiliki tampilan yang menghasilkan tautan menggunakan bidang teks result[r].thtitle. Teks dapat menyertakan tanda kutip tunggal. Jika saya tidak melarikan diri result[r].thtitledalam metode konfirmasi, Javascript akan rusak:

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

Catatan: :htmldeklarasi judul secara ajaib di-escape oleh Rails.

Noddinoff
sumber