Help us understand the problem. What is going on with this article?

[Rails]ERBのエスケープを自在に扱おうぜ

More than 5 years have passed since last update.

コメントにてご指摘をいただきました

HTMLタグを動的に生成する必要がある場合も、content_tagや(aタグでは)link_toなど、Railsの用意しているヘルパーを使えば、HTMLとして出力するかエスケープするかを適宜判断してくれます(自分でhやhtml_safeしなくて問題ありません)。

using_helper.rb
def return_url2(text)
  link_to text, 'http://google.com/'
end

純粋な文字列リテラルを.html_safeするのはありかもしれませんが、どこから来るかわからない入力で、テキストからHTMLを生成するのは、(ユーザーからHTMLを受け付けることが本当に必要な場合など)よほどの場合をのぞいて避けるべきでしょう。

Rails3からはHTMLタグが自動エスケープする

Rails3からの機能らしいんですが、
ERBで

<%= @text %>

とかやって@text内の文字列をHTMLに変換するときにHTMLタグ等を自動でエスケープするようになってます。

これはユーザーに任意で文字列を入力してもらうときのセキュリティ対策として必須です。

けどHTMLタグをHelperとかで作成したい場合とか困ります。

application_helper.rb
def return_url
  return "<a href="http://google.com">http://google.com</a>"
end
test.html.erb
<%= return_url %>

↓こうHTML出力される

<a href="http://google.com">http://google.com</a>

html_safeメソッドを使おう

そんなときは html_safeメソッドを使う

<%= return_url.html_safe %>

とすると、http://google.com がこちらで意図したとおりaタグで出力されます。

けどセキュリティ的に心配

さっきのHelperメソッドレベルであればhtml_safeメソッドを使うだけで問題ないんですが、ユーザーが任意で入力できるテキストにこちらが意図してHTMLタグを埋め込みたい場合に困ります。

例えばメッセージ等の中にURLが組み込まれている場合、それをaタグで囲ってブラウザ上でクリックできる状態(=有効化)にしたい。。
けどメッセージはユーザーが任意で入力できるため、ユーザーが入力したHTMLタグ等はエスケープ(=無効化)したい。。

という割とよくある?ケースにはこうしたほうが良いです。

test.html.erb
<%= return_url2(h(@test_text)).html_safe %>

ちょっとわかりづらいので順を追って。。

1.controllerから取得したテキストをhメソッドでエスケープ(無効化)します。

test.html.erb
h(@test_text)

2.エスケープした後の@test_textをHelperメソッドのreturn_url2に渡します。
return_url2メソッドは任意)

test.html.erb
return_url2(h(@test_text))

3.return_url2メソッドの結果をhtml_safeにする
(こちらが意図して付けたHTMLタグは有効化する)

test.html.erb
return_url2(h(@test_text)).html_safe

4.完成。

test.html.erb
<%= return_url2(h(@test_text)).html_safe %>

まとめ

html_safeメソッド(HTMLタグの有効化)とhメソッド(HTMLタグのエスケープ=無効化)をきちんと使い分ければHTMLタグエスケープもあなたのもの!

※もうちょっといい書き方あるよってひとは是非教えて下さい!!

satoken0417
主な担当はRuby on Rails。 その他AWSでの運用やデータ分析、Objective-Cにも手を出したり
https://twitter.com/satoken0417
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした