为什么在 Rails 3 中,<%= note.html_safe %>和 <%= h note.html_safe %>给出相同的结果?
感觉就像 html_safe
向 String 类添加了一个抽象,需要了解正在发生的事情,例如,
<%= '1 <b>2</b>' %> # gives 1 <b>2</b> 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 <b>2</b> wont' escape twice
对于第 4 行,如果我们说,好吧,我们信任该字符串 - 它是安全的,但是我们为什么不能逃避呢?看来要通过 h
转义它,该字符串必须是不安全的。
所以在第1行,如果字符串没有被h
转义,它就会被自动转义。第 5 行,h
无法对字符串进行两次转义——也就是说,将 <
改为 <
后,就可以不要再逃避一次<
。
那么发生了什么事?起初,我认为 html_safe
只是在字符串上标记一个标志,表示它是安全的。那么,为什么h
不转义它呢?看来 h
和 html_escape
实际上是合作使用该标志:
1) 如果一个字符串是 html_safe,那么 h
不会转义它
2)如果一个字符串不是html_safe,那么当该字符串被添加到输出缓冲区时,它会被h
自动转义。
3) 如果 h
已经转义了一个字符串,它会被标记为 html_safe
,因此,通过 h
再次转义它不会产生任何影响。影响。 (如第 5 行,即使在 Rails 2.3.10 中,该行为也是相同的,但在 Rails 2.3.5 上 h
实际上可以转义两次......所以在 Rails 2.3.5 中,h
是一个简单的转义方法,但是到了 2.3.10,h
变得不那么简单了,但是 2.3.10 不会自动转义字符串,但是对于。出于某种原因,2.3.10 中已经存在方法 html_safe
(出于什么目的?))
它到底是如何工作的?我认为现在,有时我们在输出中没有得到我们想要的东西,我们立即将 html_safe
添加到我们的变量中,这可能非常危险,因为它可以通过这种方式引入 XSS 攻击,所以了解如何它确实有效可能非常重要。以上只是对其具体工作原理的猜测。它实际上可能是一种不同的机制吗?有支持它的文档吗?
It feels like html_safe
adds an abstraction to the String class that requires understanding of what is going on, for example,
<%= '1 <b>2</b>' %> # gives 1 <b>2</b> 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 <b>2</b> wont' escape twice
For line 4, if we are saying, ok, we trust the string -- it is safe, but why can't we escape it? It seems that to escape it by h
, the string has to be unsafe.
So on line 1, if the string is not escaped by h
, it will be automatically escaped. On line 5, h
cannot escape the string twice -- in other words, after <
is changed to <
, it can't escape it one more time to <
.
So what's happening? At first, I thought html_safe
is just tagging a flag to the string, saying it is safe. So then, why does h
not escape it? It seems that h
and html_escape
actually co-operate on using the flag:
1) If a string is html_safe, then h
will not escape it
2) If a string is not html_safe, then when the string is added to the output buffer, it will be automatically escaped by h
.
3) If h
already escaped a string, it is marked html_safe
, and therefore, escaping it one more time by h
won't take any effect. (as on Line 5, and that behavior is the same even in Rails 2.3.10, but on Rails 2.3.5 h
can actually escape it twice... so in Rails 2.3.5, h
is a simple escape method, but some where along the line to 2.3.10, h
became not as simple. But 2.3.10 won't auto escape a string, but for some reason, the method html_safe
already exists for 2.3.10 (for what purpose?))
Is that how it works exactly? I think nowadays, sometimes we don't get what we want in the output and we immediately add html_safe
to our variable, which can be quite dangerous, because it can introduce XSS attack that way, so understanding how it exactly works can be quite important. The above is only a guess of how it exactly work. Could it be actually a different mechanism and is there any doc that supports it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如您所见,对字符串调用 html_safe 会将其转换为 html 安全 SafeBuffer
http://github.com/rails/rails/blob/89978f10afbad3f856e2959a811bed1982715408/activesupport/lib/active_support/core_ext/string/output_safety.rb#L87
SafeBuffer 上的任何操作可能影响字符串安全的内容将通过 h() 传递
h 使用此标志来避免双重转义
http://github.com/rails/rails/blob/89978f10afbad3f856e2959a811bed1982715408/activesupport/lib/active_support/core_ext/string/output_safety.rb#L18
string 行为确实发生了变化,我认为你对它的运作方式基本上是正确的。一般来说,除非您确定它已经被清理,否则您不应该调用 html_safe。就像任何事情一样,使用时必须小心
As you can see, calling html_safe on a string turns it into an html safe SafeBuffer
http://github.com/rails/rails/blob/89978f10afbad3f856e2959a811bed1982715408/activesupport/lib/active_support/core_ext/string/output_safety.rb#L87
Any operations on a SafeBuffer that could affect the string safety will be passed through h()
h uses this flag to avoid double escaping
http://github.com/rails/rails/blob/89978f10afbad3f856e2959a811bed1982715408/activesupport/lib/active_support/core_ext/string/output_safety.rb#L18
The behavior did change and I think you are mostly correct about how it works. In general you should not call html_safe unless you're sure that it is already sanitized. Like anything, you have to be careful while using it
在 Rails 3 中,默认情况下所有输出都使用
h
帮助器,请参阅 http://origami.co.uk/blog/2010/02/rails-3-html-escaping
如果您不想转义,可以使用
raw
in rails 3, all output is using the
h
helper by defaultsee http://origami.co.uk/blog/2010/02/rails-3-html-escaping
if you don't want escaping you can use
raw